From 9d39a68f4e37d9ab9155ff2b8494955237aacb49 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 25 Oct 2019 12:25:08 -0700 Subject: [PATCH 1/2] Revert to #64470 --- .gitignore | 11 +- .gitmodules | 3 + CODE_OF_CONDUCT.md | 39 +- CONTRIBUTING.md | 15 +- Cargo.lock | 292 +-- README.md | 13 +- config.toml.example | 14 +- src/bootstrap/README.md | 8 +- src/bootstrap/bootstrap.py | 4 + src/bootstrap/builder.rs | 12 - src/bootstrap/cache.rs | 2 +- src/bootstrap/check.rs | 4 - src/bootstrap/compile.rs | 90 +- src/bootstrap/config.rs | 31 +- src/bootstrap/configure.py | 5 +- src/bootstrap/dist.rs | 133 +- src/bootstrap/lib.rs | 10 +- src/bootstrap/native.rs | 85 +- src/bootstrap/test.rs | 18 +- src/build_helper/lib.rs | 7 - src/ci/azure-pipelines/auto.yml | 4 +- .../steps/install-windows-build-deps.yml | 23 - src/ci/docker/README.md | 9 +- src/ci/docker/asmjs/Dockerfile | 47 + src/ci/docker/disabled/asmjs/Dockerfile | 41 - src/ci/docker/disabled/wasm32-exp/Dockerfile | 35 + src/ci/docker/disabled/wasm32-exp/node.sh | 9 + src/ci/docker/disabled/wasm32/Dockerfile | 32 + 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 + src/ci/docker/dist-various-1/Dockerfile | 1 + src/ci/docker/dist-x86_64-linux/build-curl.sh | 6 +- src/ci/docker/scripts/cross-apt-packages.sh | 1 - src/ci/docker/scripts/emscripten-wasm.sh | 37 + src/ci/docker/scripts/emscripten.sh | 21 +- src/ci/docker/wasm32/Dockerfile | 44 - src/ci/init_repo.sh | 2 +- src/ci/run.sh | 3 - src/doc/book | 2 +- src/doc/grammar.md | 813 ++++++- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc/src/SUMMARY.md | 2 - src/doc/rustc/src/codegen-options/index.md | 4 +- src/doc/rustc/src/command-line-arguments.md | 11 +- src/doc/rustc/src/json.md | 231 -- .../src/lints/listing/deny-by-default.md | 25 - .../src/lints/listing/warn-by-default.md | 24 + .../rustc/src/profile-guided-optimization.md | 11 - src/doc/rustc/src/targets/index.md | 6 - src/doc/rustc/src/targets/known-issues.md | 13 - .../src/compiler-flags/report-time.md | 80 - .../src/language-features/non-exhaustive.md | 76 + .../src/language-features/track-caller.md | 5 - src/grammar/.gitignore | 3 + src/grammar/lexer.l | 350 +++ src/grammar/parser-lalr-main.c | 193 ++ src/grammar/parser-lalr.y | 1982 +++++++++++++++++ src/grammar/raw-string-literal-ambiguity.md | 64 + src/grammar/testparser.py | 66 + src/grammar/tokens.h | 99 + src/liballoc/borrow.rs | 41 - src/liballoc/boxed.rs | 96 +- src/liballoc/collections/btree/map.rs | 2 + src/liballoc/collections/btree/set.rs | 399 ++-- src/liballoc/collections/linked_list.rs | 13 - src/liballoc/collections/linked_list/tests.rs | 43 - src/liballoc/collections/vec_deque.rs | 103 +- src/liballoc/collections/vec_deque/tests.rs | 23 - src/liballoc/fmt.rs | 389 ++-- src/liballoc/lib.rs | 4 +- src/liballoc/rc.rs | 141 +- src/liballoc/slice.rs | 17 +- src/liballoc/str.rs | 8 +- src/liballoc/string.rs | 6 +- src/liballoc/sync.rs | 126 +- src/liballoc/tests/binary_heap.rs | 13 +- src/liballoc/tests/boxed.rs | 18 - src/liballoc/tests/btree/set.rs | 136 +- src/liballoc/tests/lib.rs | 3 +- src/liballoc/tests/str.rs | 2 +- src/liballoc/tests/vec.rs | 55 +- src/liballoc/vec.rs | 73 +- src/libarena/lib.rs | 2 +- src/libcore/any.rs | 109 +- src/libcore/{array/mod.rs => array.rs} | 7 - src/libcore/array/iter.rs | 266 --- src/libcore/cell.rs | 92 +- src/libcore/char/convert.rs | 16 +- src/libcore/char/decode.rs | 50 +- src/libcore/char/methods.rs | 172 +- src/libcore/ffi.rs | 56 +- src/libcore/fmt/builders.rs | 16 +- src/libcore/fmt/mod.rs | 16 +- src/libcore/hint.rs | 16 + src/libcore/iter/traits/collect.rs | 2 +- src/libcore/iter/traits/iterator.rs | 27 +- src/libcore/lib.rs | 3 +- src/libcore/macros.rs | 90 +- src/libcore/mem/mod.rs | 20 +- src/libcore/num/dec2flt/algorithm.rs | 9 +- src/libcore/num/mod.rs | 35 +- src/libcore/num/wrapping.rs | 4 +- src/libcore/ops/unsize.rs | 2 +- src/libcore/option.rs | 23 +- src/libcore/ptr/mod.rs | 52 +- src/libcore/slice/mod.rs | 70 +- src/libcore/str/mod.rs | 5 +- src/libcore/sync/atomic.rs | 214 +- src/libcore/task/wake.rs | 2 +- src/libcore/tests/array.rs | 207 +- src/libcore/tests/fmt/builders.rs | 40 - src/libcore/tests/lib.rs | 1 - src/libfmt_macros/lib.rs | 6 +- src/libpanic_unwind/gcc.rs | 12 +- src/libpanic_unwind/seh64_gnu.rs | 2 +- src/libproc_macro/bridge/mod.rs | 1 - src/libproc_macro/lib.rs | 12 +- src/librustc/Cargo.toml | 8 +- src/librustc/arena.rs | 7 +- src/librustc/dep_graph/dep_node.rs | 44 +- src/librustc/dep_graph/graph.rs | 189 +- src/librustc/dep_graph/serialized.rs | 4 +- src/librustc/error_codes.rs | 401 ++-- src/librustc/hir/check_attr.rs | 30 +- src/librustc/hir/def.rs | 2 +- src/librustc/hir/def_id.rs | 6 +- src/librustc/hir/intravisit.rs | 3 + src/librustc/hir/lowering.rs | 95 +- src/librustc/hir/lowering/expr.rs | 92 +- src/librustc/hir/lowering/item.rs | 8 +- src/librustc/hir/map/collector.rs | 12 +- src/librustc/hir/map/def_collector.rs | 33 +- src/librustc/hir/map/definitions.rs | 55 +- src/librustc/hir/map/mod.rs | 32 +- src/librustc/hir/mod.rs | 109 +- src/librustc/hir/print.rs | 5 +- src/librustc/hir/ptr.rs | 9 +- src/librustc/ich/hcx.rs | 34 +- src/librustc/ich/impls_hir.rs | 80 +- src/librustc/ich/impls_syntax.rs | 102 +- src/librustc/ich/impls_ty.rs | 67 +- src/librustc/infer/canonical/canonicalizer.rs | 8 +- src/librustc/infer/canonical/mod.rs | 10 +- .../infer/canonical/query_response.rs | 11 +- src/librustc/infer/combine.rs | 31 +- src/librustc/infer/error_reporting/mod.rs | 51 +- .../infer/error_reporting/need_type_info.rs | 4 +- src/librustc/infer/freshen.rs | 2 +- .../infer/lexical_region_resolve/mod.rs | 76 +- src/librustc/infer/mod.rs | 68 +- src/librustc/infer/nll_relate/mod.rs | 62 +- src/librustc/infer/opaque_types/mod.rs | 18 +- .../infer/region_constraints/leak_check.rs | 8 +- src/librustc/infer/region_constraints/mod.rs | 4 +- src/librustc/infer/resolve.rs | 6 +- src/librustc/infer/type_variable.rs | 4 +- src/librustc/infer/unify_key.rs | 4 +- src/librustc/lib.rs | 11 +- src/librustc/lint/builtin.rs | 183 +- src/librustc/lint/context.rs | 240 +- src/librustc/lint/levels.rs | 36 +- src/librustc/lint/mod.rs | 107 +- src/librustc/macros.rs | 24 +- src/librustc/middle/cstore.rs | 23 +- .../middle}/dead.rs | 24 +- .../middle}/entry.rs | 16 +- src/librustc/middle/exported_symbols.rs | 7 +- src/librustc/middle/expr_use_visitor.rs | 473 +++- .../middle}/intrinsicck.rs | 16 +- .../middle}/liveness.rs | 26 +- src/librustc/middle/mem_categorization.rs | 84 +- src/librustc/middle/region.rs | 10 +- src/librustc/middle/resolve_lifetime.rs | 16 +- src/librustc/middle/stability.rs | 19 +- src/librustc/mir/cache.rs | 8 +- src/librustc/mir/interpret/allocation.rs | 42 +- src/librustc/mir/interpret/error.rs | 13 +- src/librustc/mir/interpret/mod.rs | 10 +- src/librustc/mir/interpret/value.rs | 37 +- src/librustc/mir/mod.rs | 160 +- src/librustc/mir/mono.rs | 40 +- src/librustc/mir/tcx.rs | 2 +- src/librustc/mir/traversal.rs | 2 +- src/librustc/mir/visit.rs | 227 +- src/librustc/query/mod.rs | 39 +- src/librustc/session/config.rs | 587 +++-- .../session/config}/tests.rs | 89 +- src/librustc/session/mod.rs | 73 +- src/librustc/session/search_paths.rs | 3 +- src/librustc/traits/coherence.rs | 10 +- src/librustc/traits/error_reporting.rs | 515 +---- src/librustc/traits/mod.rs | 7 +- src/librustc/traits/object_safety.rs | 4 +- src/librustc/traits/on_unimplemented.rs | 4 +- src/librustc/traits/project.rs | 9 +- src/librustc/traits/query/dropck_outlives.rs | 17 +- .../traits/query/evaluate_obligation.rs | 2 +- src/librustc/traits/query/mod.rs | 2 +- src/librustc/traits/query/outlives_bounds.rs | 7 +- .../query/type_op/implied_outlives_bounds.rs | 2 +- src/librustc/traits/query/type_op/outlives.rs | 3 +- src/librustc/traits/select.rs | 78 +- src/librustc/traits/specialize/mod.rs | 4 +- .../traits/specialize/specialization_graph.rs | 70 +- src/librustc/traits/structural_impls.rs | 14 +- src/librustc/traits/util.rs | 5 +- src/librustc/ty/binding.rs | 2 +- src/librustc/ty/codec.rs | 60 +- src/librustc/ty/context.rs | 294 +-- src/librustc/ty/error.rs | 4 +- src/librustc/ty/fast_reject.rs | 15 +- src/librustc/ty/flags.rs | 10 +- src/librustc/ty/fold.rs | 39 +- src/librustc/ty/instance.rs | 53 +- src/librustc/ty/layout.rs | 117 +- src/librustc/ty/mod.rs | 227 +- src/librustc/ty/outlives.rs | 4 +- src/librustc/ty/print/obsolete.rs | 10 +- src/librustc/ty/print/pretty.rs | 271 ++- src/librustc/ty/query/config.rs | 11 - src/librustc/ty/query/job.rs | 4 +- src/librustc/ty/query/keys.rs | 13 +- src/librustc/ty/query/mod.rs | 9 +- src/librustc/ty/query/on_disk_cache.rs | 11 +- src/librustc/ty/query/plumbing.rs | 145 +- src/librustc/ty/query/values.rs | 4 +- src/librustc/ty/relate.rs | 72 +- src/librustc/ty/structural_impls.rs | 46 +- src/librustc/ty/sty.rs | 83 +- src/librustc/ty/subst.rs | 68 +- src/librustc/ty/trait_def.rs | 7 +- src/librustc/ty/util.rs | 67 +- src/librustc/ty/walk.rs | 8 +- src/librustc/ty/wf.rs | 27 +- src/librustc/util/common.rs | 75 +- src/librustc/util/profiling.rs | 326 +-- src/librustc_apfloat/ieee.rs | 4 +- src/librustc_apfloat/lib.rs | 3 +- src/librustc_codegen_llvm/Cargo.toml | 6 + src/librustc_codegen_llvm/abi.rs | 12 +- src/librustc_codegen_llvm/allocator.rs | 6 +- src/librustc_codegen_llvm/attributes.rs | 54 +- src/librustc_codegen_llvm/back/lto.rs | 121 +- src/librustc_codegen_llvm/back/write.rs | 43 +- src/librustc_codegen_llvm/base.rs | 8 +- src/librustc_codegen_llvm/builder.rs | 1 - src/librustc_codegen_llvm/callee.rs | 2 +- src/librustc_codegen_llvm/common.rs | 42 +- src/librustc_codegen_llvm/consts.rs | 8 +- src/librustc_codegen_llvm/context.rs | 28 +- .../debuginfo/create_scope_map.rs | 4 +- src/librustc_codegen_llvm/debuginfo/gdb.rs | 4 +- .../debuginfo/metadata.rs | 40 +- src/librustc_codegen_llvm/debuginfo/mod.rs | 12 +- .../debuginfo/namespace.rs | 2 +- src/librustc_codegen_llvm/error_codes.rs | 38 + src/librustc_codegen_llvm/intrinsic.rs | 16 +- src/librustc_codegen_llvm/lib.rs | 29 +- src/librustc_codegen_llvm/llvm/ffi.rs | 10 +- src/librustc_codegen_llvm/llvm_util.rs | 3 +- src/librustc_codegen_llvm/type_of.rs | 2 +- src/librustc_codegen_ssa/Cargo.toml | 2 - src/librustc_codegen_ssa/README.md | 2 +- src/librustc_codegen_ssa/back/link.rs | 22 +- .../back/symbol_export.rs | 4 +- src/librustc_codegen_ssa/back/write.rs | 107 +- src/librustc_codegen_ssa/base.rs | 110 +- src/librustc_codegen_ssa/callee.rs | 36 + src/librustc_codegen_ssa/common.rs | 12 +- .../debuginfo/type_names.rs | 2 +- src/librustc_codegen_ssa/error_codes.rs | 35 - src/librustc_codegen_ssa/lib.rs | 14 +- src/librustc_codegen_ssa/meth.rs | 12 +- src/librustc_codegen_ssa/mir/analyze.rs | 9 +- src/librustc_codegen_ssa/mir/block.rs | 177 +- src/librustc_codegen_ssa/mir/constant.rs | 2 +- src/librustc_codegen_ssa/mir/mod.rs | 83 +- src/librustc_codegen_ssa/mir/operand.rs | 1 - src/librustc_codegen_ssa/mir/place.rs | 4 +- src/librustc_codegen_ssa/mir/rvalue.rs | 36 +- src/librustc_codegen_ssa/mir/statement.rs | 11 +- src/librustc_codegen_ssa/traits/backend.rs | 8 +- src/librustc_codegen_ssa/traits/builder.rs | 2 +- src/librustc_codegen_ssa/traits/consts.rs | 4 +- src/librustc_codegen_ssa/traits/debuginfo.rs | 4 +- src/librustc_codegen_ssa/traits/declare.rs | 4 +- src/librustc_codegen_ssa/traits/intrinsic.rs | 1 - src/librustc_codegen_ssa/traits/misc.rs | 8 +- src/librustc_codegen_ssa/traits/mod.rs | 1 - src/librustc_codegen_utils/codegen_backend.rs | 5 +- src/librustc_codegen_utils/lib.rs | 5 - src/librustc_codegen_utils/symbol_names.rs | 23 +- .../symbol_names/legacy.rs | 10 +- src/librustc_codegen_utils/symbol_names/v0.rs | 4 +- src/librustc_data_structures/Cargo.toml | 5 +- .../bit_set.rs | 74 +- .../bit_set/tests.rs | 0 src/librustc_data_structures/fingerprint.rs | 2 +- .../graph/dominators/mod.rs | 29 +- .../graph/implementation/mod.rs | 10 +- .../graph/iterate/mod.rs | 4 +- src/librustc_data_structures/graph/mod.rs | 2 +- src/librustc_data_structures/graph/scc/mod.rs | 2 +- .../graph/vec_graph/mod.rs | 2 +- .../indexed_vec.rs} | 0 src/librustc_data_structures/lib.rs | 2 + .../obligation_forest/mod.rs | 215 +- .../obligation_forest/tests.rs | 28 +- src/librustc_data_structures/sharded.rs | 32 +- .../snapshot_map/mod.rs | 2 +- src/librustc_data_structures/stable_hasher.rs | 178 +- src/librustc_data_structures/svh.rs | 6 +- src/librustc_data_structures/sync.rs | 53 +- src/librustc_data_structures/thin_vec.rs | 8 +- src/librustc_data_structures/tiny_list.rs | 4 +- .../transitive_relation.rs | 22 +- .../vec_linked_list.rs | 2 +- src/librustc_data_structures/work_queue.rs | 4 +- src/librustc_driver/Cargo.toml | 1 - src/librustc_driver/lib.rs | 40 +- .../annotate_snippet_emitter_writer.rs | 18 +- src/librustc_errors/diagnostic.rs | 131 +- src/librustc_errors/diagnostic_builder.rs | 5 - src/librustc_errors/emitter.rs | 597 +++-- src/librustc_errors/lib.rs | 47 +- src/librustc_errors/styled_buffer.rs | 2 +- .../assert_module_sources.rs | 8 +- src/librustc_incremental/persist/load.rs | 7 +- src/librustc_incremental/persist/save.rs | 8 - src/librustc_index/Cargo.toml | 14 - src/librustc_index/lib.rs | 7 - src/librustc_interface/Cargo.toml | 4 +- src/librustc_interface/interface.rs | 98 +- src/librustc_interface/lib.rs | 4 +- src/librustc_interface/passes.rs | 247 +- src/librustc_interface/profile/mod.rs | 297 +++ src/librustc_interface/profile/trace.rs | 304 +++ src/librustc_interface/queries.rs | 55 +- src/librustc_interface/util.rs | 25 +- src/librustc_lint/Cargo.toml | 1 - src/librustc_lint/builtin.rs | 54 +- src/librustc_lint/error_codes.rs | 2 +- src/librustc_lint/lib.rs | 240 +- src/librustc_lint/types.rs | 38 +- src/librustc_lint/unused.rs | 4 +- src/librustc_macros/Cargo.toml | 8 +- src/librustc_macros/src/hash_stable.rs | 12 +- src/librustc_macros/src/lib.rs | 1 + src/librustc_macros/src/query.rs | 6 +- src/librustc_metadata/Cargo.toml | 2 - src/librustc_metadata/creader.rs | 367 ++- src/librustc_metadata/cstore.rs | 173 +- src/librustc_metadata/cstore_impl.rs | 107 +- src/librustc_metadata/decoder.rs | 470 ++-- src/librustc_metadata/dependency_format.rs | 2 +- src/librustc_metadata/dynamic_lib.rs | 61 +- src/librustc_metadata/encoder.rs | 1147 ++++++---- src/librustc_metadata/foreign_modules.rs | 2 +- src/librustc_metadata/index.rs | 141 ++ src/librustc_metadata/lib.rs | 12 +- src/librustc_metadata/link_args.rs | 2 +- src/librustc_metadata/locator.rs | 198 +- src/librustc_metadata/native_libs.rs | 17 +- src/librustc_metadata/schema.rs | 173 +- src/librustc_metadata/table.rs | 239 -- src/librustc_mir/Cargo.toml | 1 - src/librustc_mir/borrow_check/borrow_set.rs | 9 +- .../borrow_check/conflict_errors.rs | 379 ++-- .../borrow_check/error_reporting.rs | 58 +- src/librustc_mir/borrow_check/flows.rs | 2 +- src/librustc_mir/borrow_check/location.rs | 4 +- src/librustc_mir/borrow_check/mod.rs | 129 +- src/librustc_mir/borrow_check/move_errors.rs | 73 +- .../borrow_check/mutability_errors.rs | 15 +- .../borrow_check/nll/constraint_generation.rs | 48 +- .../borrow_check/nll/constraints/graph.rs | 2 +- .../borrow_check/nll/constraints/mod.rs | 8 +- .../borrow_check/nll/explain_borrow/mod.rs | 161 +- src/librustc_mir/borrow_check/nll/facts.rs | 2 +- .../borrow_check/nll/member_constraints.rs | 8 +- src/librustc_mir/borrow_check/nll/mod.rs | 2 +- .../nll/region_infer/error_reporting/mod.rs | 141 +- .../error_reporting/region_name.rs | 30 +- .../region_infer/error_reporting/var_name.rs | 2 +- .../borrow_check/nll/region_infer/mod.rs | 18 +- .../borrow_check/nll/region_infer/values.rs | 12 +- src/librustc_mir/borrow_check/nll/renumber.rs | 53 +- .../nll/type_check/constraint_conversion.rs | 6 - .../nll/type_check/input_output.rs | 2 +- .../nll/type_check/liveness/local_use_map.rs | 8 +- .../nll/type_check/liveness/mod.rs | 52 +- .../nll/type_check/liveness/polonius.rs | 11 +- .../nll/type_check/liveness/trace.rs | 39 +- .../borrow_check/nll/type_check/mod.rs | 140 +- .../borrow_check/nll/type_check/relate_tys.rs | 8 +- .../borrow_check/nll/universal_regions.rs | 62 +- .../borrow_check/places_conflict.rs | 10 +- src/librustc_mir/borrow_check/used_muts.rs | 9 +- src/librustc_mir/build/expr/as_place.rs | 146 +- src/librustc_mir/build/expr/as_rvalue.rs | 42 +- src/librustc_mir/build/expr/as_temp.rs | 2 + src/librustc_mir/build/expr/into.rs | 2 +- src/librustc_mir/build/matches/mod.rs | 13 +- src/librustc_mir/build/matches/simplify.rs | 4 +- src/librustc_mir/build/matches/test.rs | 23 +- src/librustc_mir/build/matches/util.rs | 34 +- src/librustc_mir/build/mod.rs | 48 +- src/librustc_mir/build/scope.rs | 97 +- src/librustc_mir/dataflow/at_location.rs | 2 +- src/librustc_mir/dataflow/generic.rs | 131 +- src/librustc_mir/dataflow/generic/graphviz.rs | 413 ---- src/librustc_mir/dataflow/impls/borrows.rs | 6 +- .../dataflow/impls/indirect_mutation.rs | 39 +- src/librustc_mir/dataflow/impls/mod.rs | 4 +- .../dataflow/impls/storage_liveness.rs | 40 +- src/librustc_mir/dataflow/mod.rs | 10 +- .../dataflow/move_paths/builder.rs | 8 +- src/librustc_mir/dataflow/move_paths/mod.rs | 10 +- src/librustc_mir/error_codes.rs | 553 ++--- src/librustc_mir/hair/cx/block.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 9 +- src/librustc_mir/hair/cx/mod.rs | 2 +- src/librustc_mir/hair/pattern/_match.rs | 659 ++---- src/librustc_mir/hair/pattern/check_match.rs | 55 +- src/librustc_mir/hair/pattern/mod.rs | 182 +- src/librustc_mir/interpret/cast.rs | 9 +- src/librustc_mir/interpret/eval_context.rs | 18 +- src/librustc_mir/interpret/intern.rs | 7 +- .../interpret/intrinsics/type_name.rs | 7 +- src/librustc_mir/interpret/memory.rs | 22 +- src/librustc_mir/interpret/operand.rs | 30 +- src/librustc_mir/interpret/place.rs | 36 +- src/librustc_mir/interpret/snapshot.rs | 10 +- src/librustc_mir/interpret/terminator.rs | 5 +- src/librustc_mir/interpret/validity.rs | 2 +- src/librustc_mir/lib.rs | 3 +- src/librustc_mir/lints.rs | 6 +- src/librustc_mir/monomorphize/collector.rs | 43 +- src/librustc_mir/monomorphize/item.rs | 204 ++ src/librustc_mir/monomorphize/partitioning.rs | 71 +- src/librustc_mir/shim.rs | 40 +- src/librustc_mir/transform/add_call_guards.rs | 2 +- .../transform/check_consts/qualifs.rs | 11 +- .../transform/check_consts/resolver.rs | 24 +- .../transform/check_consts/validation.rs | 46 +- src/librustc_mir/transform/check_unsafety.rs | 33 +- .../transform/cleanup_post_borrowck.rs | 14 +- src/librustc_mir/transform/const_prop.rs | 238 +- src/librustc_mir/transform/copy_prop.rs | 134 +- src/librustc_mir/transform/deaggregator.rs | 1 - src/librustc_mir/transform/elaborate_drops.rs | 2 +- src/librustc_mir/transform/erase_regions.rs | 22 +- src/librustc_mir/transform/generator.rs | 149 +- src/librustc_mir/transform/inline.rs | 105 +- src/librustc_mir/transform/instcombine.rs | 50 +- src/librustc_mir/transform/mod.rs | 8 +- src/librustc_mir/transform/no_landing_pads.rs | 20 +- src/librustc_mir/transform/promote_consts.rs | 77 +- src/librustc_mir/transform/qualify_consts.rs | 255 +-- .../transform/qualify_min_const_fn.rs | 6 +- .../transform/remove_noop_landing_pads.rs | 17 +- src/librustc_mir/transform/rustc_peek.rs | 320 ++- src/librustc_mir/transform/simplify.rs | 104 +- .../transform/uniform_array_move_out.rs | 138 +- src/librustc_mir/util/aggregate.rs | 11 +- src/librustc_mir/util/alignment.rs | 4 +- src/librustc_mir/util/def_use.rs | 74 +- src/librustc_mir/util/elaborate_drops.rs | 66 +- src/librustc_mir/util/graphviz.rs | 2 +- src/librustc_mir/util/liveness.rs | 4 +- src/librustc_mir/util/patch.rs | 2 +- src/librustc_mir/util/pretty.rs | 2 +- src/librustc_passes/Cargo.toml | 3 - src/librustc_passes/ast_validation.rs | 5 +- src/librustc_passes/error_codes.rs | 310 +-- src/librustc_passes/lib.rs | 13 +- src/librustc_passes/rvalue_promotion.rs | 658 ++++++ src/librustc_plugin/Cargo.toml | 1 - src/librustc_plugin/lib.rs | 2 +- src/librustc_plugin/load.rs | 21 +- src/librustc_plugin/registry.rs | 46 +- src/librustc_privacy/error_codes.rs | 23 +- src/librustc_privacy/lib.rs | 14 +- src/librustc_resolve/Cargo.toml | 1 - src/librustc_resolve/build_reduced_graph.rs | 87 +- src/librustc_resolve/diagnostics.rs | 57 +- src/librustc_resolve/error_codes.rs | 279 +-- src/librustc_resolve/late.rs | 297 +-- src/librustc_resolve/late/diagnostics.rs | 56 +- src/librustc_resolve/lib.rs | 297 +-- src/librustc_resolve/macros.rs | 36 +- src/librustc_resolve/resolve_imports.rs | 99 +- src/librustc_save_analysis/dump_visitor.rs | 51 +- src/librustc_save_analysis/lib.rs | 5 +- src/librustc_target/Cargo.toml | 1 - src/librustc_target/abi/call/asmjs.rs | 47 + src/librustc_target/abi/call/mod.rs | 27 +- src/librustc_target/abi/call/wasm32.rs | 52 +- .../abi/call/wasm32_bindgen_compat.rs | 27 - src/librustc_target/abi/call/x86.rs | 2 +- src/librustc_target/abi/mod.rs | 11 +- .../spec/aarch64_unknown_none.rs | 4 +- .../spec/aarch64_unknown_none_softfloat.rs | 37 - .../spec/asmjs_unknown_emscripten.rs | 44 +- src/librustc_target/spec/mod.rs | 14 +- .../spec/wasm32_experimental_emscripten.rs | 44 + .../spec/wasm32_unknown_emscripten.rs | 41 +- src/librustc_target/spec/wasm32_wasi.rs | 4 - src/librustc_traits/chalk_context/mod.rs | 4 +- .../chalk_context/program_clauses/builtin.rs | 5 +- .../chalk_context/resolvent_ops.rs | 17 +- src/librustc_traits/chalk_context/unify.rs | 2 +- src/librustc_traits/dropck_outlives.rs | 113 +- src/librustc_traits/evaluate_obligation.rs | 2 - src/librustc_traits/generic_types.rs | 12 +- src/librustc_traits/lowering/mod.rs | 4 +- src/librustc_typeck/Cargo.toml | 1 - src/librustc_typeck/astconv.rs | 48 +- src/librustc_typeck/check/_match.rs | 8 +- src/librustc_typeck/check/callee.rs | 17 +- src/librustc_typeck/check/cast.rs | 43 +- src/librustc_typeck/check/closure.rs | 156 +- src/librustc_typeck/check/coercion.rs | 116 +- src/librustc_typeck/check/demand.rs | 10 +- src/librustc_typeck/check/dropck.rs | 90 +- src/librustc_typeck/check/expr.rs | 50 +- .../check/generator_interior.rs | 25 +- src/librustc_typeck/check/intrinsic.rs | 6 +- src/librustc_typeck/check/method/confirm.rs | 20 +- src/librustc_typeck/check/method/mod.rs | 65 +- src/librustc_typeck/check/method/suggest.rs | 244 +- src/librustc_typeck/check/mod.rs | 212 +- src/librustc_typeck/check/op.rs | 4 +- src/librustc_typeck/check/pat.rs | 2 +- src/librustc_typeck/check/regionck.rs | 54 +- src/librustc_typeck/check/upvar.rs | 69 +- src/librustc_typeck/check/wfcheck.rs | 55 +- src/librustc_typeck/check/writeback.rs | 30 +- src/librustc_typeck/coherence/mod.rs | 5 +- src/librustc_typeck/collect.rs | 194 +- .../constrained_generic_params.rs | 4 +- src/librustc_typeck/error_codes.rs | 209 +- src/librustc_typeck/impl_wf_check.rs | 2 +- src/librustc_typeck/lib.rs | 6 +- src/librustc_typeck/outlives/explicit.rs | 2 +- src/librustc_typeck/outlives/utils.rs | 9 +- src/librustdoc/Cargo.toml | 2 +- src/librustdoc/clean/auto_trait.rs | 4 +- src/librustdoc/clean/blanket_impl.rs | 2 +- src/librustdoc/clean/cfg.rs | 4 +- src/librustdoc/clean/inline.rs | 20 +- src/librustdoc/clean/mod.rs | 78 +- src/librustdoc/config.rs | 10 +- src/librustdoc/core.rs | 22 +- src/librustdoc/doctree.rs | 4 +- src/librustdoc/html/format.rs | 15 +- src/librustdoc/html/highlight.rs | 4 +- src/librustdoc/html/item_type.rs | 2 +- src/librustdoc/html/render.rs | 10 +- src/librustdoc/html/static/main.js | 3 +- src/librustdoc/html/static/noscript.css | 8 - src/librustdoc/html/static/rustdoc.css | 4 +- src/librustdoc/html/static/themes/dark.css | 2 +- src/librustdoc/html/static/themes/light.css | 2 +- src/librustdoc/lib.rs | 8 +- .../passes/check_code_block_syntax.rs | 3 +- .../passes/collect_intra_doc_links.rs | 6 +- src/librustdoc/test.rs | 12 +- src/librustdoc/visit_ast.rs | 2 +- src/libserialize/collection_impls.rs | 4 +- src/libserialize/json.rs | 21 +- src/libstd/Cargo.toml | 2 +- src/libstd/backtrace.rs | 2 +- src/libstd/collections/hash/map.rs | 60 +- src/libstd/collections/hash/set.rs | 8 +- src/libstd/error.rs | 10 +- src/libstd/ffi/c_str.rs | 28 +- src/libstd/fs.rs | 26 +- src/libstd/future.rs | 1 - src/libstd/io/stdio.rs | 2 +- src/libstd/keyword_docs.rs | 67 +- src/libstd/lib.rs | 11 +- src/libstd/net/addr.rs | 17 +- src/libstd/net/ip.rs | 237 +- src/libstd/net/udp.rs | 6 +- src/libstd/panic.rs | 32 +- src/libstd/panicking.rs | 53 +- src/libstd/path.rs | 35 +- src/libstd/primitive_docs.rs | 12 +- src/libstd/process.rs | 12 +- src/libstd/rt.rs | 3 + src/libstd/sync/mpsc/mod.rs | 20 + src/libstd/sync/once.rs | 5 +- src/libstd/sys/unix/fast_thread_local.rs | 3 +- src/libstd/sys/unix/fd.rs | 34 +- src/libstd/sys/unix/fs.rs | 242 +- src/libstd/sys/unix/rand.rs | 2 +- src/libstd/sys/vxworks/fs.rs | 26 +- src/libstd/sys/vxworks/rwlock.rs | 2 +- src/libstd/sys/wasi/thread.rs | 8 +- src/libstd/sys/windows/fs.rs | 2 +- src/libstd/sys/windows/handle.rs | 2 +- src/libstd/sys/windows/mutex.rs | 2 +- src/libstd/sys/windows/process.rs | 5 +- src/libstd/sys/windows/rand.rs | 2 +- src/libstd/sys/windows/thread_local.rs | 2 +- src/libstd/sys/windows/time.rs | 4 +- src/libstd/sys_common/backtrace.rs | 60 +- src/libstd/sys_common/os_str_bytes.rs | 8 +- src/libstd/thread/local.rs | 5 +- src/libstd/thread/mod.rs | 3 + src/libstd/time.rs | 51 +- src/libsyntax/Cargo.toml | 1 - src/libsyntax/ast.rs | 103 +- src/libsyntax/attr/builtin.rs | 59 +- src/libsyntax/attr/mod.rs | 125 +- src/libsyntax/config.rs | 28 +- src/libsyntax/early_buffered_lints.rs | 1 - src/libsyntax/error_codes.rs | 88 +- .../ext}/allocator.rs | 4 +- .../ext}/base.rs | 60 +- .../ext}/build.rs | 16 +- .../ext}/expand.rs | 355 +-- .../ext}/mbe.rs | 8 +- .../ext}/mbe/macro_check.rs | 14 +- .../ext}/mbe/macro_parser.rs | 73 +- .../ext}/mbe/macro_rules.rs | 77 +- .../ext}/mbe/quoted.rs | 17 +- .../ext}/mbe/transcribe.rs | 17 +- .../ext}/placeholders.rs | 44 +- .../ext}/proc_macro.rs | 38 +- .../ext}/proc_macro_server.rs | 35 +- src/libsyntax/feature_gate/accepted.rs | 4 - src/libsyntax/feature_gate/active.rs | 32 +- src/libsyntax/feature_gate/builtin_attrs.rs | 39 +- src/libsyntax/feature_gate/check.rs | 239 +- src/libsyntax/feature_gate/mod.rs | 3 +- src/libsyntax/json.rs | 43 +- src/libsyntax/json/tests.rs | 186 -- src/libsyntax/lib.rs | 65 +- src/libsyntax/mut_visit.rs | 16 +- src/libsyntax/parse/{parser => }/attr.rs | 80 +- .../parse/{parser => }/diagnostics.rs | 359 +-- src/libsyntax/parse/lexer/comments.rs | 2 +- src/libsyntax/parse/lexer/mod.rs | 4 +- src/libsyntax/parse/lexer/tokentrees.rs | 24 +- src/libsyntax/parse/literal.rs | 192 +- src/libsyntax/parse/mod.rs | 287 ++- src/libsyntax/parse/parser.rs | 684 ++++-- src/libsyntax/parse/parser/expr.rs | 213 +- src/libsyntax/parse/parser/generics.rs | 6 +- src/libsyntax/parse/parser/item.rs | 1163 ++++------ src/libsyntax/parse/parser/module.rs | 12 +- src/libsyntax/parse/parser/pat.rs | 186 +- src/libsyntax/parse/parser/path.rs | 37 +- src/libsyntax/parse/parser/stmt.rs | 13 +- src/libsyntax/parse/parser/ty.rs | 45 +- src/libsyntax/parse/token.rs | 155 +- src/libsyntax/print/pprust.rs | 46 +- src/libsyntax/print/pprust/tests.rs | 1 + src/libsyntax/ptr.rs | 8 +- src/libsyntax/sess.rs | 146 -- src/libsyntax/source_map.rs | 32 +- src/libsyntax/tests.rs | 11 +- src/libsyntax/tokenstream.rs | 313 +-- src/libsyntax_expand/Cargo.toml | 26 - src/libsyntax_expand/lib.rs | 39 - src/libsyntax_ext/Cargo.toml | 1 - src/libsyntax_ext/asm.rs | 2 +- src/libsyntax_ext/assert.rs | 2 +- src/libsyntax_ext/cfg.rs | 2 +- src/libsyntax_ext/cmdline_attrs.rs | 9 +- src/libsyntax_ext/compile_error.rs | 2 +- src/libsyntax_ext/concat.rs | 2 +- src/libsyntax_ext/concat_idents.rs | 2 +- src/libsyntax_ext/deriving/bounds.rs | 2 +- src/libsyntax_ext/deriving/clone.rs | 24 +- src/libsyntax_ext/deriving/cmp/eq.rs | 2 +- src/libsyntax_ext/deriving/cmp/ord.rs | 2 +- src/libsyntax_ext/deriving/cmp/partial_eq.rs | 2 +- src/libsyntax_ext/deriving/cmp/partial_ord.rs | 2 +- src/libsyntax_ext/deriving/debug.rs | 2 +- src/libsyntax_ext/deriving/decodable.rs | 2 +- src/libsyntax_ext/deriving/default.rs | 4 +- src/libsyntax_ext/deriving/encodable.rs | 2 +- src/libsyntax_ext/deriving/generic/mod.rs | 12 +- src/libsyntax_ext/deriving/generic/ty.rs | 2 +- src/libsyntax_ext/deriving/hash.rs | 2 +- src/libsyntax_ext/deriving/mod.rs | 2 +- src/libsyntax_ext/env.rs | 2 +- src/libsyntax_ext/format.rs | 7 +- src/libsyntax_ext/global_allocator.rs | 7 +- src/libsyntax_ext/global_asm.rs | 2 +- src/libsyntax_ext/lib.rs | 8 +- src/libsyntax_ext/log_syntax.rs | 2 +- src/libsyntax_ext/plugin_macro_defs.rs | 4 +- src/libsyntax_ext/proc_macro_harness.rs | 49 +- src/libsyntax_ext/source_util.rs | 41 +- src/libsyntax_ext/standard_library_imports.rs | 8 +- src/libsyntax_ext/test.rs | 50 +- src/libsyntax_ext/test_harness.rs | 36 +- src/libsyntax_ext/trace_macros.rs | 2 +- src/libsyntax_ext/util.rs | 11 - src/libsyntax_pos/Cargo.toml | 1 - src/libsyntax_pos/lib.rs | 119 +- src/libsyntax_pos/symbol.rs | 246 +- src/libsyntax_pos/symbol/tests.rs | 7 + src/libsyntax_pos/tests.rs | 31 +- src/libtest/bench.rs | 258 --- src/libtest/cli.rs | 444 ---- src/libtest/console.rs | 308 --- src/libtest/event.rs | 41 - src/libtest/formatters/json.rs | 42 +- src/libtest/formatters/mod.rs | 23 +- src/libtest/formatters/pretty.rs | 158 +- src/libtest/formatters/terse.rs | 40 +- src/libtest/helpers/concurrency.rs | 143 -- src/libtest/helpers/exit_code.rs | 20 - src/libtest/helpers/isatty.rs | 33 - src/libtest/helpers/metrics.rs | 50 - src/libtest/helpers/mod.rs | 8 - src/libtest/helpers/sink.rs | 24 - src/libtest/lib.rs | 1757 ++++++++++++--- src/libtest/options.rs | 90 - src/libtest/stats.rs | 2 +- src/libtest/stats/tests.rs | 2 +- src/libtest/test_result.rs | 107 - src/libtest/tests.rs | 194 +- src/libtest/time.rs | 206 -- src/libtest/types.rs | 145 -- src/llvm-emscripten | 1 + src/llvm-project | 2 +- src/test/codegen/c-variadic.rs | 1 - src/test/codegen/drop.rs | 1 - src/test/codegen/extern-functions.rs | 19 + .../codegen/external-no-mangle-statics.rs | 1 - src/test/codegen/link_section.rs | 1 - src/test/codegen/no-output-asm-is-volatile.rs | 2 + .../codegen/non-terminate/infinite-loop-1.rs | 17 - .../codegen/non-terminate/infinite-loop-2.rs | 19 - .../non-terminate/infinite-recursion.rs | 14 - src/test/codegen/nounwind-extern.rs | 6 + src/test/codegen/personality_lifetimes.rs | 1 - .../codegen/repr-transparent-aggregates-2.rs | 3 +- .../simd-intrinsic-float-abs.rs | 2 + .../simd-intrinsic-float-ceil.rs | 2 + .../simd-intrinsic-float-cos.rs | 2 + .../simd-intrinsic-float-exp.rs | 2 + .../simd-intrinsic-float-exp2.rs | 2 + .../simd-intrinsic-float-floor.rs | 2 + .../simd-intrinsic-float-fma.rs | 2 + .../simd-intrinsic-float-fsqrt.rs | 2 + .../simd-intrinsic-float-log.rs | 2 + .../simd-intrinsic-float-log10.rs | 2 + .../simd-intrinsic-float-log2.rs | 2 + .../simd-intrinsic-float-minmax.rs | 1 + .../simd-intrinsic-float-pow.rs | 2 + .../simd-intrinsic-float-powi.rs | 2 + .../simd-intrinsic-float-sin.rs | 2 + ...intrinsic-generic-arithmetic-saturating.rs | 160 +- .../simd-intrinsic-generic-bitmask.rs | 6 +- .../simd-intrinsic-generic-gather.rs | 1 + .../simd-intrinsic-generic-scatter.rs | 1 + src/test/codegen/union-abi.rs | 1 - src/test/codegen/unwind-extern-exports.rs | 20 - src/test/codegen/unwind-extern-imports.rs | 42 - src/test/compile-fail/consts/const-err3.rs | 1 - src/test/compile-fail/weak-lang-item.rs | 2 +- src/test/incremental/change_crate_dep_kind.rs | 1 - src/test/incremental/commandline-args.rs | 1 - .../incremental/const-generics/issue-61338.rs | 14 - .../incremental/const-generics/issue-61516.rs | 16 - .../incremental/const-generics/issue-62536.rs | 12 - .../incremental/const-generics/issue-64087.rs | 11 - .../incremental/const-generics/issue-65623.rs | 14 - src/test/incremental/hashes/for_loops.rs | 2 +- .../incremental/hashes/let_expressions.rs | 8 +- .../incremental/hashes/loop_expressions.rs | 2 +- .../incremental/hashes/while_let_loops.rs | 2 +- src/test/incremental/hashes/while_loops.rs | 2 +- .../incremental/remapped_paths_cc/main.rs | 1 - src/test/incremental/span_hash_stable/main.rs | 1 - .../incremental/spans_in_type_debuginfo.rs | 1 - .../spans_significant_w_debuginfo.rs | 1 - src/test/mir-opt/box_expr.rs | 2 +- src/test/mir-opt/const_prop/aggregate.rs | 25 - src/test/mir-opt/const_prop/boxes.rs | 56 - src/test/mir-opt/const_prop/discriminant.rs | 53 - src/test/mir-opt/const_prop/reify_fn_ptr.rs | 2 +- src/test/mir-opt/const_prop/repeat.rs | 37 - .../mir-opt/generator-storage-dead-unwind.rs | 2 +- src/test/mir-opt/issue-41110.rs | 2 +- src/test/mir-opt/issue-62289.rs | 2 +- .../mir-opt/no-spurious-drop-after-call.rs | 2 +- .../mir-opt/packed-struct-drop-aligned.rs | 2 +- src/test/mir-opt/remove_fake_borrows.rs | 2 +- src/test/mir-opt/retag.rs | 2 +- .../simplify-locals-removes-unused-consts.rs | 89 - src/test/mir-opt/slice-drop-shim.rs | 4 +- .../never_type => run-fail}/adjust_never.rs | 1 - .../call-fn-never-arg.rs | 1 - .../{ui/never_type => run-fail}/cast-never.rs | 1 - .../never-associated-type.rs | 1 - .../never_type => run-fail}/never-type-arg.rs | 1 - src/test/run-fail/overflowing-rsh-5.rs | 1 - src/test/run-fail/overflowing-rsh-6.rs | 1 - .../hotplug_codegen_backend/the_backend.rs | 12 +- src/test/run-make-fulldeps/issue-19371/foo.rs | 1 - .../linker-output-non-utf8/Makefile | 23 + .../linker-output-non-utf8/exec.rs | 6 + .../linker-output-non-utf8/library.rs | 10 + .../sanitizer-address/Makefile | 3 - .../sanitizer-staticlib-link/Makefile | 14 +- .../sanitizer-staticlib-link/program.rs | 10 - .../target-without-atomic-cas/Makefile | 2 +- .../run-make/wasm-custom-section/Makefile | 2 +- .../wasm-custom-sections-opt/Makefile | 2 +- .../run-make/wasm-export-all-symbols/Makefile | 2 +- src/test/run-make/wasm-import-module/Makefile | 2 +- src/test/run-make/wasm-panic-small/Makefile | 2 +- .../wasm-symbols-not-exported/Makefile | 2 +- .../wasm-symbols-not-imported/Makefile | 2 +- .../rustdoc-ui/doc-test-doctest-feature.rs | 15 - .../doc-test-doctest-feature.stdout | 6 - .../rustdoc-ui/doc-test-rustdoc-feature.rs | 14 - .../doc-test-rustdoc-feature.stdout | 6 - .../failed-doctest-missing-codes.stdout | 14 +- .../rustdoc-ui/failed-doctest-output.stdout | 8 +- .../rustdoc-ui/unparseable-doc-test.stdout | 8 +- src/test/rustdoc/const-generics/const-impl.rs | 1 - src/test/rustdoc/macro-in-closure.rs | 9 - src/test/rustdoc/sanitizer-option.rs | 17 - src/test/rustdoc/variadic.rs | 2 +- src/test/ui-fulldeps/ast_stmt_expr_attr.rs | 5 +- .../ui-fulldeps/auxiliary/attr-plugin-test.rs | 3 +- .../auxiliary/issue-40001-plugin.rs | 10 +- .../auxiliary/lint-for-crate-rpass.rs | 24 +- .../ui-fulldeps/auxiliary/lint-for-crate.rs | 5 +- .../auxiliary/lint-group-plugin-test.rs | 8 +- .../ui-fulldeps/auxiliary/lint-plugin-test.rs | 6 +- .../ui-fulldeps/auxiliary/lint-tool-test.rs | 8 +- src/test/ui-fulldeps/auxiliary/plugin-args.rs | 5 +- .../ui-fulldeps/auxiliary/roman-numerals.rs | 3 +- src/test/ui-fulldeps/gated-plugin.rs | 3 +- src/test/ui-fulldeps/gated-plugin.stderr | 10 +- .../lint_pass_impl_without_macro.rs | 10 +- .../lint_pass_impl_without_macro.stderr | 2 +- src/test/ui-fulldeps/issue-15778-fail.rs | 1 - src/test/ui-fulldeps/issue-15778-fail.stderr | 9 - src/test/ui-fulldeps/issue-15778-pass.stderr | 8 - src/test/ui-fulldeps/issue-40001.stderr | 8 - .../lint-group-plugin-deny-cmdline.rs | 2 - .../lint-group-plugin-deny-cmdline.stderr | 12 +- src/test/ui-fulldeps/lint-group-plugin.stderr | 8 - .../lint-plugin-cmdline-allow.stderr | 8 - src/test/ui-fulldeps/lint-plugin-deny-attr.rs | 1 - .../ui-fulldeps/lint-plugin-deny-attr.stderr | 12 +- .../ui-fulldeps/lint-plugin-deny-cmdline.rs | 1 - .../lint-plugin-deny-cmdline.stderr | 10 +- .../ui-fulldeps/lint-plugin-forbid-attrs.rs | 1 - .../lint-plugin-forbid-attrs.stderr | 14 +- .../ui-fulldeps/lint-plugin-forbid-cmdline.rs | 2 +- .../lint-plugin-forbid-cmdline.stderr | 8 - src/test/ui-fulldeps/lint-plugin.stderr | 8 - .../lint-tool-cmdline-allow.stderr | 8 - src/test/ui-fulldeps/lint-tool-test.rs | 1 - src/test/ui-fulldeps/lint-tool-test.stderr | 26 +- src/test/ui-fulldeps/llvm-pass-plugin.stderr | 8 - .../ui-fulldeps/lto-syntax-extension.stderr | 8 - src/test/ui-fulldeps/macro-crate-rlib.rs | 1 - src/test/ui-fulldeps/macro-crate-rlib.stderr | 8 - .../ui-fulldeps/mod_dir_path_canonicalized.rs | 3 +- src/test/ui-fulldeps/newtype_index.rs | 4 +- .../outlive-expansion-phase.stderr | 8 - src/test/ui-fulldeps/plugin-args-1.stderr | 8 - src/test/ui-fulldeps/plugin-args-2.stderr | 8 - src/test/ui-fulldeps/plugin-args-3.stderr | 8 - .../ui-fulldeps/plugin-attr-register-deny.rs | 1 - .../plugin-attr-register-deny.stderr | 16 +- src/test/ui-fulldeps/plugin-reexport.rs | 1 - src/test/ui-fulldeps/plugin-reexport.stderr | 12 +- src/test/ui-fulldeps/pprust-expr-roundtrip.rs | 5 +- .../ui-fulldeps/roman-numerals-macro.stderr | 8 - src/test/ui/.gitattributes | 3 - .../abort-on-c-abi.rs} | 30 +- .../ui/{ => abi}/macros/macros-in-extern.rs | 21 +- .../ui/abi/macros/macros-in-extern.stderr | 30 + .../abi/proc-macro/auxiliary/test-macros.rs | 112 + .../{ => abi}/proc-macro/macros-in-extern.rs | 6 +- .../ui/abi/proc-macro/macros-in-extern.stderr | 30 + src/test/ui/abi/statics/static-mut-foreign.rs | 4 - .../always-inhabited-union-ref.rs | 0 .../always-inhabited-union-ref.stderr | 0 src/test/ui/anon-params-denied-2018.stderr | 8 - .../ui/anonymous-higher-ranked-lifetime.rs | 11 + .../anonymous-higher-ranked-lifetime.stderr | 141 +- src/test/ui/asm/issue-51431.rs | 10 - src/test/ui/asm/issue-51431.stderr | 8 - ...ssociated-const-impl-wrong-lifetime.stderr | 2 +- ...iated-const-type-parameter-arrays-2.stderr | 4 +- ...ociated-const-type-parameter-arrays.stderr | 4 +- src/test/ui/associated-const/issue-63496.rs | 9 - .../ui/associated-const/issue-63496.stderr | 21 - src/test/ui/associated-item/issue-48027.rs | 8 - .../ui/associated-item/issue-48027.stderr | 21 - .../bad-bounds-on-assoc-in-trait.stderr | 18 +- .../ui/associated-type-bounds/union-bounds.rs | 15 +- .../associated-types-bound-failure.fixed | 29 - .../associated-types-bound-failure.rs | 2 - .../associated-types-bound-failure.stderr | 7 +- .../associated-types-for-unimpl-trait.fixed | 15 - .../associated-types-for-unimpl-trait.rs | 3 - .../associated-types-for-unimpl-trait.stderr | 9 +- ...types-invalid-trait-ref-issue-18865.stderr | 4 +- .../associated-types-no-suitable-bound.stderr | 7 +- ...ated-types-no-suitable-supertrait-2.stderr | 7 +- ...ciated-types-no-suitable-supertrait.stderr | 7 +- ...ated-trait-in-method-without-default.fixed | 30 - ...related-trait-in-method-without-default.rs | 1 - ...ted-trait-in-method-without-default.stderr | 9 +- .../associated-types-unsized.fixed | 14 - .../associated-types-unsized.rs | 3 - .../associated-types-unsized.stderr | 5 +- ...ject-fn-ret-contravariant.transmute.stderr | 3 +- .../project-fn-ret-invariant.transmute.stderr | 3 +- src/test/ui/associated-types/issue-44153.rs | 19 - .../ui/associated-types/issue-44153.stderr | 16 - src/test/ui/associated-types/issue-48010.rs | 23 - src/test/ui/associated-types/issue-64855-2.rs | 5 - src/test/ui/associated-types/issue-64855.rs | 8 - .../ui/associated-types/issue-64855.stderr | 9 - src/test/ui/ast-json/ast-json-output.stdout | 2 +- .../async-assoc-fn-anon-lifetimes.rs | 23 - ...ync-block-control-flow-static-semantics.rs | 2 +- ...block-control-flow-static-semantics.stderr | 26 +- .../async-borrowck-escaping-block-error.fixed | 12 - .../async-borrowck-escaping-block-error.rs | 12 - ...async-borrowck-escaping-block-error.stderr | 22 - ...wck-escaping-closure-error.polonius.stderr | 16 + src/test/ui/async-await/async-error-span.rs | 2 +- .../ui/async-await/async-error-span.stderr | 4 +- .../ui/async-await/async-fn-nonsend.stderr | 24 +- .../async-await/async-fn-size-moved-locals.rs | 5 +- .../async-fn-size-uninit-locals.rs | 103 - src/test/ui/async-await/async-fn-size.rs | 8 +- .../incorrect-syntax-suggestions.stderr | 3 +- .../edition-deny-async-fns-2015.stderr | 12 +- src/test/ui/async-await/issue-60709.rs | 1 - .../issue-64130-non-send-future-diags.rs | 25 - .../issue-64130-non-send-future-diags.stderr | 23 - .../ui/async-await/issues/issue-51719.stderr | 1 - .../ui/async-await/issues/issue-51751.stderr | 1 - .../async-await/issues/issue-62009-1.stderr | 3 +- .../async-await/issues/issue-62009-2.stderr | 1 - .../ui/async-await/issues/issue-63388-1.rs | 4 +- .../async-await/issues/issue-63388-1.stderr | 9 +- .../async-await/issues/issue-63388-2.stderr | 13 +- src/test/ui/async-await/issues/issue-64964.rs | 22 - src/test/ui/async-await/issues/issue-65159.rs | 10 - .../ui/async-await/issues/issue-65159.stderr | 9 - .../issues/non-async-enclosing-span.stderr | 1 - .../async-await/return-ty-raw-ptr-coercion.rs | 25 - .../async-await/return-ty-unsize-coercion.rs | 45 - 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 | 4 +- .../async-await/unresolved_type_param.stderr | 4 +- src/test/ui/async-await/unused-lifetime.rs | 42 - .../ui/async-await/unused-lifetime.stderr | 32 - src/test/ui/auto-trait-validation.stderr | 3 +- .../ui/bad/bad-method-typaram-kind.stderr | 3 +- .../fn-arg-incomplete-pattern-drop-order.rs | 2 +- src/test/ui/binding/match-arm-statics.rs | 1 - ...k-escaping-closure-error-2.polonius.stderr | 16 + src/test/ui/borrowck/issue-64453.rs | 24 - src/test/ui/borrowck/issue-64453.stderr | 34 - ...ref-mut-in-let-issue-46557.polonius.stderr | 59 + ...regions-bound-missing-bound-in-impl.stderr | 4 +- ...al-binding-from-desugaring.polonius.stderr | 16 + ...phase-surprise-no-conflict.polonius.stderr | 148 ++ src/test/ui/break-outside-loop.rs | 8 - src/test/ui/break-outside-loop.stderr | 10 +- src/test/ui/builtin-clone-unwind.rs | 2 +- ...builtin-superkinds-double-superkind.stderr | 10 +- .../builtin-superkinds-in-metadata.stderr | 5 +- ...builtin-superkinds-typaram-not-send.stderr | 5 +- src/test/ui/c-variadic/variadic-ffi-1.stderr | 4 +- .../ui/c-variadic/variadic-ffi-4.nll.stderr | 40 +- src/test/ui/c-variadic/variadic-ffi-4.rs | 11 +- src/test/ui/c-variadic/variadic-ffi-4.stderr | 198 +- .../call-fn-never-arg-wrong-type.rs | 0 .../call-fn-never-arg-wrong-type.stderr | 0 src/test/ui/catch-unwind-bang.rs | 2 +- src/test/ui/cfg/cfg_stmt_expr.rs | 4 +- .../ui/check-static-values-constraints.stderr | 2 +- src/test/ui/check_match/issue-43253.rs | 19 +- src/test/ui/check_match/issue-43253.stderr | 28 +- .../expect-fn-supply-fn.stderr | 4 +- ...ds-cant-promote-superkind-in-struct.stderr | 6 +- .../ui/closures/closure-bounds-subtype.stderr | 4 +- .../expect-region-supply-region.stderr | 4 +- src/test/ui/closures/issue-41366.rs | 13 - src/test/ui/closures/issue-41366.stderr | 22 - src/test/ui/closures/issue-52437.rs | 5 - src/test/ui/closures/issue-52437.stderr | 15 - .../coercion/coerce-issue-49593-box-never.rs | 2 +- .../ui/coherence/auxiliary/coherence_lib.rs | 4 +- .../coherence-unsafe-trait-object-impl.rs | 18 - .../coherence-unsafe-trait-object-impl.stderr | 12 - .../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/impl-foreign-for-foreign.rs | 17 - .../coherence/impl-foreign-for-foreign.stderr | 12 - .../impl-foreign-for-foreign[foreign].rs | 25 - .../impl-foreign-for-foreign[foreign].stderr | 30 - .../impl-foreign-for-foreign[local].rs | 16 - .../impl-foreign-for-fundamental[foreign].rs | 21 - ...pl-foreign-for-fundamental[foreign].stderr | 21 - .../impl-foreign-for-fundamental[local].rs | 17 - .../ui/coherence/impl-foreign-for-local.rs | 15 - .../impl-foreign[foreign]-for-foreign.rs | 17 - .../impl-foreign[foreign]-for-foreign.stderr | 12 - .../impl-foreign[foreign]-for-local.rs | 16 - ...reign[fundemental[foreign]]-for-foreign.rs | 26 - ...n[fundemental[foreign]]-for-foreign.stderr | 30 - ...foreign[fundemental[local]]-for-foreign.rs | 18 - .../impl[t]-foreign-for-foreign[t].rs | 23 - .../impl[t]-foreign-for-foreign[t].stderr | 21 - .../impl[t]-foreign-for-fundamental[t].rs | 17 - .../impl[t]-foreign-for-fundamental[t].stderr | 11 - ...]-foreign[foreign[t]_local]-for-foreign.rs | 14 - ...[t]-foreign[foreign]-for-fundamental[t].rs | 20 - ...foreign[foreign]-for-fundamental[t].stderr | 19 - .../impl[t]-foreign[foreign]-for-t.rs | 16 - .../impl[t]-foreign[foreign]-for-t.stderr | 11 - ...[t]-foreign[fundamental[t]]-for-foreign.rs | 20 - ...foreign[fundamental[t]]-for-foreign.stderr | 19 - ...eign[fundamental[t]]-for-fundamental[t].rs | 19 - ...[fundamental[t]]-for-fundamental[t].stderr | 19 - ...pl[t]-foreign[fundamental[t]]-for-local.rs | 17 - .../impl[t]-foreign[fundamental[t]]-for-t.rs | 19 - ...pl[t]-foreign[fundamental[t]]-for-t.stderr | 19 - ...reign[fundamental[t]_local]-for-foreign.rs | 20 - ...n[fundamental[t]_local]-for-foreign.stderr | 19 - ...eign[fundemental[local]]-for-foreign[t].rs | 17 - .../impl[t]-foreign[local]-for-foreign.rs | 16 - .../impl[t]-foreign[local]-for-foreign[t].rs | 17 - ...eign[local]-for-fundamental[foreign[t]].rs | 19 - ...pl[t]-foreign[local]-for-fundamental[t].rs | 20 - ...]-foreign[local]-for-fundamental[t].stderr | 19 - .../impl[t]-foreign[local]-for-local.rs | 15 - .../coherence/impl[t]-foreign[local]-for-t.rs | 16 - .../impl[t]-foreign[local]-for-t.stderr | 11 - ...reign[local_fundamental[t]]-for-foreign.rs | 19 - .../impl[t]-foreign[t]-for-foreign.rs | 16 - .../impl[t]-foreign[t]-for-foreign.stderr | 11 - .../impl[t]-foreign[t]-for-fundamental.rs | 20 - .../impl[t]-foreign[t]-for-fundamental.stderr | 19 - .../coherence/impl[t]-foreign[t]-for-local.rs | 15 - .../ui/coherence/impl[t]-foreign[t]-for-t.rs | 16 - .../coherence/impl[t]-foreign[t]-for-t.stderr | 11 - .../coherence/re-rebalance-coherence-rpass.rs | 14 + src/test/ui/conflicting-repr-hints.stderr | 1 - .../array-impls/into-iter-impls-length-32.rs | 41 - .../into-iter-no-impls-length-33.rs | 53 - .../into-iter-no-impls-length-33.stderr | 122 - .../auxiliary/const_generic_lib.rs | 9 - .../const-argument-cross-crate-mismatch.rs | 10 - ...const-argument-cross-crate-mismatch.stderr | 21 - .../const-argument-cross-crate.rs | 12 - .../const-param-in-trait-ungated.stderr | 4 +- ...aram-type-depends-on-type-param-ungated.rs | 2 +- ...-type-depends-on-type-param-ungated.stderr | 18 +- .../const-param-type-depends-on-type-param.rs | 3 +- ...st-param-type-depends-on-type-param.stderr | 19 +- .../const-parameter-uppercase-lint.stderr | 2 +- .../ui/const-generics/fn-const-param-call.rs | 20 - .../const-generics/fn-const-param-call.stderr | 8 - .../ui/const-generics/fn-const-param-infer.rs | 26 - .../fn-const-param-infer.stderr | 45 - .../forbid-non-structural_match-types.rs | 13 - .../forbid-non-structural_match-types.stderr | 17 - .../{issues => }/issue-60263.rs | 0 .../{issues => }/issue-60263.stderr | 4 +- .../issue-60818-struct-constructors.rs | 0 .../issue-60818-struct-constructors.stderr | 0 .../{issues => }/issue-61336-1.rs | 0 .../{issues => }/issue-61336-1.stderr | 0 .../{issues => }/issue-61336-2.rs | 0 .../{issues => }/issue-61336-2.stderr | 0 .../{issues => }/issue-61336.rs | 0 .../{issues => }/issue-61336.stderr | 0 .../{issues => }/issue-61422.rs | 0 .../{issues => }/issue-61422.stderr | 0 .../{issues => }/issue-61432.rs | 0 .../{issues => }/issue-61432.stderr | 0 .../{issues => }/issue-64519.rs | 0 .../{issues => }/issue-64519.stderr | 0 ...sue-62187-encountered-polymorphic-const.rs | 16 - ...62187-encountered-polymorphic-const.stderr | 16 - .../issues/issue-62579-no-match.rs | 15 - .../issues/issue-62579-no-match.stderr | 8 - .../ui/const-generics/issues/issue-65675.rs | 10 - .../const-generics/issues/issue-65675.stderr | 8 - .../raw-ptr-const-param-deref.rs | 19 - .../raw-ptr-const-param-deref.stderr | 8 - .../ui/const-generics/raw-ptr-const-param.rs | 9 - .../const-generics/raw-ptr-const-param.stderr | 20 - .../slice-const-param-mismatch.rs | 14 - .../slice-const-param-mismatch.stderr | 38 - .../ui/const-generics/slice-const-param.rs | 19 - .../const-generics/slice-const-param.stderr | 8 - .../struct-with-invalid-const-param.stderr | 1 - .../types-mismatch-const-args.rs | 19 - .../types-mismatch-const-args.stderr | 29 - .../ui/consts/auxiliary/external_macro.rs | 14 - src/test/ui/consts/const-err2.rs | 1 - src/test/ui/consts/const-err2.stderr | 8 +- src/test/ui/consts/const-err3.rs | 1 - src/test/ui/consts/const-err3.stderr | 8 +- .../ui/consts/const-eval/const_let.stderr | 1 - .../ui/consts/const-eval/generic-slice.rs | 31 - .../ui/consts/const-eval/generic-slice.stderr | 30 - src/test/ui/consts/const-eval/issue-50814.rs | 1 + .../ui/consts/const-eval/issue-50814.stderr | 12 +- src/test/ui/consts/const-eval/issue-64908.rs | 20 - src/test/ui/consts/const-eval/issue-64970.rs | 15 - .../ui/consts/const-eval/issue-64970.stderr | 8 - src/test/ui/consts/const-eval/issue-65394.rs | 10 - .../ui/consts/const-eval/issue-65394.stderr | 11 - .../write-to-uninhabited-enum-variant.rs | 28 - .../const-extern-fn-call-extern-fn.rs | 23 - .../const-extern-fn-call-extern-fn.stderr | 21 - .../const-extern-fn-min-const-fn.rs | 13 - .../const-extern-fn-min-const-fn.stderr | 39 - .../const-extern-fn-requires-unsafe.rs | 10 - .../const-extern-fn-requires-unsafe.stderr | 19 - .../consts/const-extern-fn/const-extern-fn.rs | 35 - .../feature-gate-const_extern_fn.rs | 12 - .../feature-gate-const_extern_fn.stderr | 57 - .../consts/const-external-macro-const-err.rs | 13 - .../const-external-macro-const-err.stderr | 11 - src/test/ui/consts/const-int-pow-rpass.rs | 11 - .../ui/consts/const-int-saturating-arith.rs | 1 + .../ui/consts/const-match-check.eval1.stderr | 7 - .../ui/consts/const-match-check.eval2.stderr | 7 - .../consts/const-match-check.matchck.stderr | 28 - src/test/ui/consts/const-prop-ice.rs | 1 - src/test/ui/consts/const-prop-ice.stderr | 8 +- src/test/ui/consts/issue-64506.rs | 20 - src/test/ui/consts/issue-64662.rs | 10 - src/test/ui/consts/issue-64662.stderr | 15 - src/test/ui/consts/issue-65348.rs | 23 - .../consts/min_const_fn/min_const_fn.stderr | 4 +- ...gate-unleash_the_miri_inside_of_you.stderr | 1 - .../ui/consts/miri_unleashed/non_const_fn.rs | 13 - .../consts/miri_unleashed/non_const_fn.stderr | 29 - .../consts/promote_const_let.polonius.stderr | 29 + .../ui/consts/too_generic_eval_ice.stderr | 8 +- src/test/ui/conversion-methods.stderr | 2 +- src/test/ui/debuginfo-lto.rs | 1 - .../{never_type => }/defaulted-never-note.rs | 0 .../defaulted-never-note.stderr | 0 .../ui/deprecation/deprecation-sanity.stderr | 2 +- .../ui/deprecation/derive_on_deprecated.rs | 6 - src/test/ui/did_you_mean/issue-40396.rs | 10 +- src/test/ui/did_you_mean/issue-40396.stderr | 25 +- ...1679-tilde-bitwise-negation-attempt.stderr | 2 +- ...issue-43871-enum-instead-of-variant.stderr | 28 +- ...ssue-56028-there-is-an-enum-variant.stderr | 4 +- .../{never_type => }/dispatch_from_dyn_zst.rs | 0 .../diverging-fallback-control-flow.rs | 1 - src/test/ui/drop/dynamic-drop-async.rs | 2 +- src/test/ui/drop/dynamic-drop.rs | 14 +- ...dropck_trait_cycle_checked.polonius.stderr | 78 + .../dst/dst-object-from-unsized-type.stderr | 6 +- src/test/ui/empty/empty-never-array.stderr | 7 - .../ui/empty/empty-struct-braces-expr.stderr | 12 - .../ui/empty/empty-struct-braces-pat-1.stderr | 3 - .../ui/empty/empty-struct-braces-pat-2.stderr | 6 - .../ui/empty/empty-struct-braces-pat-3.stderr | 6 - .../ui/empty/empty-struct-tuple-pat.stderr | 7 +- src/test/ui/enum/enum-variant-type-2.stderr | 1 - src/test/ui/error-codes/E0005.stderr | 7 - src/test/ui/error-codes/E0392.stderr | 2 +- src/test/ui/error-codes/E0423.stderr | 5 +- src/test/ui/error-codes/E0424.stderr | 14 +- src/test/ui/error-codes/E0478.stderr | 4 +- src/test/ui/error-codes/E0617.rs | 6 +- src/test/ui/error-codes/E0617.stderr | 20 +- ...E0621-does-not-trigger-for-closures.stderr | 1 - src/test/ui/exhaustive_integer_patterns.rs | 9 +- .../ui/exhaustive_integer_patterns.stderr | 34 +- .../explicit-self-lifetime-mismatch.stderr | 8 +- src/test/ui/expr_attr_paren_order.stderr | 2 +- src/test/ui/extern/extern-const.fixed | 3 +- src/test/ui/extern/extern-const.rs | 3 +- src/test/ui/extern/extern-const.stderr | 2 +- ...llow-unwind-when-calling-panic-directly.rs | 65 - ...sue-64655-extern-rust-must-allow-unwind.rs | 83 - .../issue-43106-gating-of-builtin-attrs.rs | 7 +- ...issue-43106-gating-of-builtin-attrs.stderr | 442 ++-- src/test/ui/feature-gates/bench.rs | 4 - src/test/ui/feature-gates/bench.stderr | 13 +- .../feature-gate-associated_type_bounds.rs | 10 +- ...feature-gate-associated_type_bounds.stderr | 11 +- .../feature-gate-box_patterns.rs | 3 - .../feature-gate-box_patterns.stderr | 11 +- .../feature-gates/feature-gate-box_syntax.rs | 5 +- .../feature-gate-box_syntax.stderr | 2 +- .../feature-gate-const_generics-ptr.rs | 9 - .../feature-gate-const_generics-ptr.stderr | 39 - .../feature-gate-const_generics.rs | 5 - .../feature-gate-const_generics.stderr | 19 +- .../feature-gate-crate_visibility_modifier.rs | 3 - ...ture-gate-crate_visibility_modifier.stderr | 11 +- .../feature-gates/feature-gate-decl_macro.rs | 4 - .../feature-gate-decl_macro.stderr | 11 +- .../feature-gate-exclusive-range-pattern.rs | 6 +- ...eature-gate-exclusive-range-pattern.stderr | 15 +- .../feature-gate-exhaustive-patterns.rs | 1 - .../feature-gate-exhaustive-patterns.stderr | 9 +- .../feature-gate-label_break_value.rs | 5 +- .../feature-gate-label_break_value.stderr | 2 +- .../feature-gate-macros_in_extern.rs | 27 + .../feature-gate-macros_in_extern.stderr | 30 + .../feature-gate-non_exhaustive.rs | 10 + .../feature-gate-non_exhaustive.stderr | 12 + .../feature-gate-object_safe_for_dispatch.rs | 41 - ...ature-gate-object_safe_for_dispatch.stderr | 46 - .../ui/feature-gates/feature-gate-plugin.rs | 3 +- .../feature-gates/feature-gate-plugin.stderr | 10 +- .../feature-gate-plugin_registrar.rs | 5 +- .../feature-gate-plugin_registrar.stderr | 21 +- .../feature-gate-repr-simd.stderr | 3 +- .../feature-gate-track_caller.rs | 5 - .../feature-gate-track_caller.stderr | 12 - .../feature-gates/feature-gate-trait-alias.rs | 9 - .../feature-gate-trait-alias.stderr | 11 +- .../feature-gates/feature-gate-try_blocks.rs | 7 +- .../feature-gate-try_blocks.stderr | 4 +- .../feature-gate-type_ascription.rs | 5 +- .../feature-gate-type_ascription.stderr | 2 +- .../feature-gate-untagged_unions.rs | 4 +- .../feature-gate-untagged_unions.stderr | 35 +- .../feature-gate-unwind-attributes.rs | 1 - .../feature-gate-unwind-attributes.stderr | 2 +- src/test/ui/fmt/format-string-error.rs | 2 - src/test/ui/fmt/format-string-error.stderr | 8 +- .../ui/for-loop-while/loop-break-value.rs | 1 - src/test/ui/gated-bad-feature.stderr | 3 +- src/test/ui/generator/issue-58888.rs | 1 - src/test/ui/generator/panic-drops.rs | 2 +- src/test/ui/generator/panic-safe.rs | 2 +- ...escapes-but-not-over-yield.polonius.stderr | 20 + src/test/ui/generator/resume-after-return.rs | 2 +- src/test/ui/generator/size-moved-locals.rs | 1 - ...-type-param-can-reference-self-in-trait.rs | 20 - ...e-param-can-reference-self-in-trait.stderr | 12 - ...efault-type-param-cannot-reference-self.rs | 45 - ...lt-type-param-cannot-reference-self.stderr | 39 - ...incorrect-explicit-lifetime-name-needed.rs | 14 - ...rrect-explicit-lifetime-name-needed.stderr | 21 - ...hr-subtype.free_inv_x_vs_free_inv_y.stderr | 8 +- .../hr-subtype.free_x_vs_free_y.stderr | 4 +- .../ui/hrtb/due-to-where-clause.nll.stderr | 8 - src/test/ui/hrtb/due-to-where-clause.rs | 3 + src/test/ui/hrtb/due-to-where-clause.stderr | 2 +- ...igher-ranker-supertraits-transitive.stderr | 5 +- .../hrtb-higher-ranker-supertraits.stderr | 10 +- src/test/ui/hrtb/issue-30786.nll.stderr | 12 +- src/test/ui/hrtb/issue-30786.rs | 4 +- src/test/ui/hygiene/globs.stderr | 2 +- .../ui/hygiene/no_implicit_prelude.stderr | 2 +- .../hygiene/rustc-macro-transparency.stderr | 2 +- src/test/ui/hygiene/trait_items.stderr | 2 +- src/test/ui/hygiene/unpretty-debug.stdout | 2 +- src/test/ui/if/if-no-match-bindings.stderr | 40 +- src/test/ui/if/ifmt-bad-arg.stderr | 10 +- .../ui/{never_type => }/impl-for-never.rs | 3 +- .../dyn-trait.stderr | 3 +- .../ui/impl-trait/hidden-lifetimes.stderr | 4 +- src/test/ui/impl-trait/issue-55872-1.stderr | 7 +- .../issues/universal-issue-48703.rs | 2 +- .../issues/universal-issue-48703.stderr | 6 +- ...iversal-turbofish-in-method-issue-50950.rs | 2 +- ...sal-turbofish-in-method-issue-50950.stderr | 8 +- .../must_outlive_least_region_or_bound.stderr | 8 +- .../no-method-suggested-traits.stderr | 12 +- .../impl-trait/region-escape-via-bound.stderr | 2 +- .../static-return-lifetime-infered.stderr | 4 +- .../mismatched_trait_impl-2.stderr | 1 - .../mismatched_trait_impl.nll.stderr | 3 +- .../mismatched_trait_impl.stderr | 3 +- src/test/ui/include-single-expr-helper-1.rs | 5 - src/test/ui/include-single-expr-helper.rs | 5 - src/test/ui/include-single-expr.rs | 6 - src/test/ui/include-single-expr.stderr | 10 - .../ui/infinite/infinite-autoderef.stderr | 2 +- .../ui/inner-static-type-parameter.stderr | 6 +- src/test/ui/intrinsics/intrinsic-alignment.rs | 3 +- src/test/ui/intrinsics/intrinsics-integer.rs | 1 + src/test/ui/invalid/invalid-plugin-attr.rs | 1 - .../ui/invalid/invalid-plugin-attr.stderr | 8 - src/test/ui/{issues => }/issue-53912.rs | 0 src/test/ui/{issues => }/issue-59020.rs | 0 .../ui/issues/auxiliary/issue-57271-lib.rs | 11 - src/test/ui/issues/issue-10200.stderr | 2 +- src/test/ui/issues/issue-10291.stderr | 2 +- src/test/ui/issues/issue-10465.stderr | 2 +- .../ui/{never_type => issues}/issue-13352.rs | 0 .../{never_type => issues}/issue-13352.stderr | 0 src/test/ui/issues/issue-13867.rs | 1 + src/test/ui/issues/issue-14875.rs | 2 +- src/test/ui/issues/issue-16683.stderr | 3 +- src/test/ui/issues/issue-17001.stderr | 1 - src/test/ui/issues/issue-17252.stderr | 6 +- src/test/ui/issues/issue-17405.stderr | 1 - src/test/ui/issues/issue-17546.stderr | 5 +- .../ui/issues/issue-17718-const-naming.stderr | 2 +- src/test/ui/issues/issue-17740.stderr | 4 +- src/test/ui/issues/issue-17758.stderr | 3 +- src/test/ui/issues/issue-17904-2.stderr | 2 +- src/test/ui/issues/issue-17905-2.stderr | 4 +- src/test/ui/issues/issue-18119.stderr | 1 - src/test/ui/issues/issue-19086.stderr | 3 - src/test/ui/issues/issue-19538.stderr | 1 - src/test/ui/issues/issue-19883.stderr | 1 - src/test/ui/issues/issue-20005.stderr | 2 +- src/test/ui/issues/issue-20413.stderr | 2 +- src/test/ui/issues/issue-20692.stderr | 1 - .../ui/issues/issue-20831-debruijn.stderr | 9 +- src/test/ui/issues/issue-21449.stderr | 1 - src/test/ui/issues/issue-21475.rs | 2 +- .../ui/{never_type => issues}/issue-2149.rs | 0 .../{never_type => issues}/issue-2149.stderr | 0 src/test/ui/issues/issue-21837.stderr | 6 +- src/test/ui/issues/issue-22037.stderr | 1 - src/test/ui/issues/issue-22384.stderr | 1 - src/test/ui/issues/issue-22872.stderr | 3 +- src/test/ui/issues/issue-23189.stderr | 1 - src/test/ui/issues/issue-23302-1.stderr | 4 +- src/test/ui/issues/issue-23302-2.stderr | 4 +- src/test/ui/issues/issue-23302-3.stderr | 22 +- src/test/ui/issues/issue-23477.rs | 5 +- .../issue-24687-embed-debuginfo/main.rs | 1 - .../ui/issues/issue-24945-repeat-dash-opts.rs | 1 - src/test/ui/issues/issue-26251.rs | 2 - src/test/ui/issues/issue-26459.stderr | 1 - src/test/ui/issues/issue-26484.rs | 1 - src/test/ui/issues/issue-27060-2.stderr | 3 +- src/test/ui/issues/issue-27078.stderr | 5 +- src/test/ui/issues/issue-27815.stderr | 1 - src/test/ui/issues/issue-27942.stderr | 4 +- src/test/ui/issues/issue-28848.stderr | 4 +- src/test/ui/issues/issue-29948.rs | 2 +- src/test/ui/issues/issue-30535.stderr | 1 - src/test/ui/issues/issue-31561.stderr | 7 - src/test/ui/issues/issue-32004.stderr | 5 +- src/test/ui/issues/issue-33096.rs | 1 - src/test/ui/issues/issue-33992.rs | 2 +- src/test/ui/issues/issue-34569.rs | 1 - src/test/ui/issues/issue-35675.stderr | 4 +- src/test/ui/issues/issue-36163.stderr | 6 +- src/test/ui/issues/issue-36299.stderr | 4 +- src/test/ui/issues/issue-36638.stderr | 2 +- src/test/ui/issues/issue-36856.rs | 1 - src/test/ui/issues/issue-3707.stderr | 2 +- src/test/ui/issues/issue-37534.stderr | 4 +- src/test/ui/issues/issue-37884.stderr | 2 +- src/test/ui/issues/issue-38604.stderr | 1 - src/test/ui/issues/issue-38821.stderr | 1 + src/test/ui/issues/issue-39175.stderr | 2 +- src/test/ui/issues/issue-42210.rs | 1 - src/test/ui/issues/issue-42312.stderr | 5 +- src/test/ui/issues/issue-43189.stderr | 2 +- .../issues/issue-43784-associated-type.stderr | 6 +- .../ui/issues/issue-43784-supertrait.stderr | 6 +- src/test/ui/issues/issue-43853.rs | 2 +- .../ui/{never_type => issues}/issue-44402.rs | 3 +- src/test/ui/issues/issue-45731.rs | 1 - src/test/ui/issues/issue-46332.stderr | 2 +- src/test/ui/issues/issue-46519.rs | 2 - src/test/ui/issues/issue-47486.rs | 4 - src/test/ui/issues/issue-47486.stderr | 19 - src/test/ui/issues/issue-48508.rs | 1 - src/test/ui/issues/issue-49579.rs | 1 + .../option-as_deref.rs | 2 + .../option-as_deref.stderr | 2 +- .../option-as_deref_mut.rs | 2 + .../option-as_deref_mut.stderr | 2 +- src/test/ui/issues/issue-50571.rs | 6 - src/test/ui/issues/issue-50571.stderr | 13 - src/test/ui/issues/issue-52213.stderr | 5 +- src/test/ui/issues/issue-52262.rs | 25 - src/test/ui/issues/issue-52262.stderr | 9 - src/test/ui/issues/issue-54348.rs | 2 - src/test/ui/issues/issue-54348.stderr | 16 +- src/test/ui/issues/issue-55796.stderr | 5 +- src/test/ui/issues/issue-57271.rs | 24 - src/test/ui/issues/issue-57271.stderr | 25 - .../issue-57399-self-return-impl-trait.rs | 22 - .../issue-57399-self-return-impl-trait.stderr | 8 - src/test/ui/issues/issue-58022.rs | 18 - src/test/ui/issues/issue-58022.stderr | 19 - src/test/ui/issues/issue-58344.rs | 50 - src/test/ui/issues/issue-58344.stderr | 19 - src/test/ui/issues/issue-58463.rs | 2 - src/test/ui/issues/issue-60218.rs | 19 - src/test/ui/issues/issue-60218.stderr | 15 - src/test/ui/issues/issue-63983.stderr | 8 +- src/test/ui/issues/issue-64620.rs | 5 - src/test/ui/issues/issue-64620.stderr | 9 - .../ui/issues/issue-64792-bad-unicode-ctor.rs | 5 - .../issue-64792-bad-unicode-ctor.stderr | 15 - ...issue-65284-suggest-generic-trait-bound.rs | 11 - ...e-65284-suggest-generic-trait-bound.stderr | 15 - src/test/ui/issues/issue-65611.rs | 63 - src/test/ui/issues/issue-65611.stderr | 18 - .../ui/iterators/iter-count-overflow-debug.rs | 2 +- .../iterators/iter-position-overflow-debug.rs | 2 +- .../ui/iterators/iter-step-overflow-debug.rs | 2 +- .../ui/iterators/iter-sum-overflow-debug.rs | 2 +- .../iter-sum-overflow-overflow-checks.rs | 2 +- .../ui/json-bom-plus-crlf-multifile-aux.rs | 27 - src/test/ui/json-bom-plus-crlf-multifile.rs | 12 - .../ui/json-bom-plus-crlf-multifile.stderr | 86 - src/test/ui/json-bom-plus-crlf.rs | 27 - src/test/ui/json-bom-plus-crlf.stderr | 86 - .../kindck/kindck-impl-type-params.nll.stderr | 16 +- .../ui/kindck/kindck-impl-type-params.stderr | 16 +- ...copy-bound.object_safe_for_dispatch.stderr | 25 - .../ui/kindck/kindck-inherited-copy-bound.rs | 11 +- ...err => kindck-inherited-copy-bound.stderr} | 7 +- src/test/ui/lexical-scopes.stderr | 3 +- .../lifetime-bound-will-change-warning.stderr | 4 +- src/test/ui/lint/lint-exceeding-bitshifts2.rs | 2 +- .../ui/lint/lint-exceeding-bitshifts2.stderr | 8 +- .../ui/lint/lint-non-camel-case-types.stderr | 10 +- .../lint/lint-non-snake-case-functions.stderr | 6 +- .../ui/lint/lint-non-uppercase-statics.stderr | 2 +- src/test/ui/lint/lint-unused-variables.rs | 15 - src/test/ui/lint/lint-unused-variables.stderr | 28 +- .../ui/lint/lint-uppercase-variables.stderr | 6 +- src/test/ui/lint/must_use-unit.rs | 1 + src/test/ui/lint/must_use-unit.stderr | 6 +- src/test/ui/lint/not_found.stderr | 2 +- src/test/ui/lint/reasons.stderr | 2 +- .../redundant-semi-proc-macro.stderr | 2 +- .../lint/unused_parens_json_suggestion.fixed | 7 +- .../ui/lint/unused_parens_json_suggestion.rs | 7 +- .../lint/unused_parens_json_suggestion.stderr | 106 +- ...unused_parens_remove_json_suggestion.fixed | 21 +- .../unused_parens_remove_json_suggestion.rs | 21 +- ...nused_parens_remove_json_suggestion.stderr | 658 +++++- src/test/ui/lint/use_suggestion_json.stderr | 2 +- src/test/ui/lub-if.stderr | 4 +- src/test/ui/lub-match.stderr | 4 +- src/test/ui/macros/issue-54441.rs | 2 + src/test/ui/macros/issue-54441.stderr | 2 +- .../ui/macros/macro-comma-behavior-rpass.rs | 2 - src/test/ui/macros/macro-first-set.rs | 6 + src/test/ui/macros/macro-meta-items-modern.rs | 11 - src/test/ui/macros/macros-in-extern-rpass.rs | 30 + src/test/ui/macros/same-sequence-span.rs | 1 + src/test/ui/macros/same-sequence-span.stderr | 8 +- src/test/ui/malformed/malformed-plugin-1.rs | 1 - .../ui/malformed/malformed-plugin-1.stderr | 8 - src/test/ui/malformed/malformed-plugin-2.rs | 1 - .../ui/malformed/malformed-plugin-2.stderr | 8 - src/test/ui/malformed/malformed-plugin-3.rs | 1 - .../ui/malformed/malformed-plugin-3.stderr | 8 - .../ui/match/match-range-fail-dominate.rs | 22 +- .../ui/match/match-range-fail-dominate.stderr | 22 +- .../ui/match/match-ref-mut-invariance.stderr | 4 +- .../match/match-ref-mut-let-invariance.stderr | 4 +- .../match/non-exhaustive-defined-here.stderr | 28 - src/test/ui/maybe-bounds-where.stderr | 2 +- src/test/ui/methods/method-path-in-pattern.rs | 6 - .../ui/methods/method-path-in-pattern.stderr | 21 +- .../mir-dataflow/indirect-mutation-offset.rs | 41 - .../indirect-mutation-offset.stderr | 10 - src/test/ui/mir/mir_calls_to_shims.rs | 2 +- src/test/ui/mir/mir_drop_order.rs | 2 +- src/test/ui/mismatched_types/abridged.rs | 9 - src/test/ui/mismatched_types/abridged.stderr | 30 +- src/test/ui/mismatched_types/issue-36053-2.rs | 1 + .../ui/mismatched_types/issue-36053-2.stderr | 10 +- src/test/ui/mod/mod_file_disambig.stderr | 1 - src/test/ui/multiple-plugin-registrars.stderr | 14 - src/test/ui/namespace/namespace-mix.stderr | 3 - .../never-assign-dead-code.rs | 4 +- .../never-assign-dead-code.stderr | 4 +- .../never-assign-wrong-type.rs | 0 .../never-assign-wrong-type.stderr | 0 .../never-from-impl-is-reserved.rs | 0 .../never-from-impl-is-reserved.stderr | 0 src/test/ui/{never_type => }/never-result.rs | 1 - .../ui/{never_type => }/never-type-rvalues.rs | 0 .../ui/{never_type => }/never_coercions.rs | 0 .../{never_type => }/never_transmute_never.rs | 2 +- src/test/ui/nll/empty-type-predicate-2.rs | 18 - src/test/ui/nll/empty-type-predicate.rs | 4 +- src/test/ui/nll/get_default.polonius.stderr | 5 +- src/test/ui/nll/issue-50716.stderr | 2 +- src/test/ui/nll/issue-52742.stderr | 2 +- src/test/ui/nll/issue-55394.stderr | 3 +- src/test/ui/nll/issue-55401.stderr | 2 +- src/test/ui/nll/issue-63154-normalize.rs | 34 - .../loan_ends_mid_block_pair.polonius.stderr | 15 + .../ui/nll/normalization-bounds-error.stderr | 5 +- .../nll/polonius/polonius-smoke-test.stderr | 4 +- src/test/ui/nll/promoted-liveness.rs | 8 - src/test/ui/nll/relate_tys/fn-subtype.rs | 10 - src/test/ui/nll/relate_tys/fn-subtype.stderr | 8 - src/test/ui/nll/relate_tys/trait-hrtb.rs | 16 - src/test/ui/nll/relate_tys/trait-hrtb.stderr | 8 - ...return-ref-mut-issue-46557.polonius.stderr | 15 + .../ui/nll/trait-associated-constant.stderr | 4 +- .../ui/nll/type-alias-free-regions.stderr | 5 +- .../constant-in-expr-inherent-1.stderr | 3 +- .../constant-in-expr-normalize.stderr | 2 +- .../constant-in-expr-trait-item-1.stderr | 2 +- .../constant-in-expr-trait-item-2.stderr | 2 +- .../constant-in-expr-trait-item-3.stderr | 3 +- src/test/ui/no-patterns-in-args-macro.stderr | 2 +- src/test/ui/no-patterns-in-args.stderr | 3 +- src/test/ui/not-panic/not-panic-safe.stderr | 1 - .../float-int-invalid-const-cast.rs | 1 + src/test/ui/numbers-arithmetic/i128.rs | 3 + .../next-power-of-two-overflow-debug.rs | 2 +- src/test/ui/numbers-arithmetic/u128-as-f32.rs | 1 + src/test/ui/numbers-arithmetic/u128.rs | 2 + .../object-lifetime-default-elision.stderr | 9 +- ...ifetime-default-from-rptr-box-error.stderr | 2 +- ...time-default-from-rptr-struct-error.stderr | 2 +- .../object-lifetime-default-mybox.stderr | 2 +- ...ted-consts.object_safe_for_dispatch.stderr | 15 - .../object-safety-associated-consts.rs | 6 +- ...=> object-safety-associated-consts.stderr} | 2 +- ...y-generics.object_safe_for_dispatch.stderr | 27 - .../object-safety/object-safety-generics.rs | 10 +- ...r.stderr => object-safety-generics.stderr} | 4 +- ...tions-Self.object_safe_for_dispatch.stderr | 27 - .../object-safety-mentions-Self.rs | 20 +- ...err => object-safety-mentions-Self.stderr} | 8 +- .../object-safety-no-static.curr.stderr | 12 - ...-no-static.object_safe_for_dispatch.stderr | 15 - .../object-safety/object-safety-no-static.rs | 16 +- ...ty-sized-2.object_safe_for_dispatch.stderr | 13 - .../ui/object-safety/object-safety-sized-2.rs | 9 +- ...rr.stderr => object-safety-sized-2.stderr} | 2 +- ...fety-sized.object_safe_for_dispatch.stderr | 13 - .../ui/object-safety/object-safety-sized.rs | 7 +- ...curr.stderr => object-safety-sized.stderr} | 2 +- src/test/ui/occurs-check-2.stderr | 2 +- src/test/ui/occurs-check.stderr | 2 +- .../issue-64879-trailing-before-guard.rs | 15 - .../issue-64879-trailing-before-guard.stderr | 20 - .../or-patterns/multiple-pattern-typo.stderr | 24 +- .../or-patterns-syntactic-fail.stderr | 8 - .../or-patterns/or-patterns-syntactic-pass.rs | 1 - .../ui/or-patterns/remove-leading-vert.fixed | 27 +- .../ui/or-patterns/remove-leading-vert.rs | 27 +- .../ui/or-patterns/remove-leading-vert.stderr | 134 +- src/test/ui/panic-runtime/libtest-unwinds.rs | 10 + .../ui/panic-runtime/libtest-unwinds.stderr | 4 + .../panic-runtime/transitive-link-a-bunch.rs | 2 +- .../ui/panic-runtime/want-unwind-got-abort.rs | 2 +- .../panic-runtime/want-unwind-got-abort2.rs | 2 +- .../panic-uninitialized-zeroed.rs | 2 +- .../ui/parser/doc-inside-trait-item.stderr | 1 - src/test/ui/parser/intersection-patterns.rs | 40 - .../ui/parser/intersection-patterns.stderr | 33 - src/test/ui/parser/issue-33413.rs | 1 - src/test/ui/parser/issue-33413.stderr | 14 +- .../issue-65122-mac-invoc-in-mut-patterns.rs | 26 - ...sue-65122-mac-invoc-in-mut-patterns.stderr | 45 - .../mismatched-delim-brace-empty-block.rs | 5 - .../mismatched-delim-brace-empty-block.stderr | 14 - .../ui/parser/no-const-fn-in-extern-block.rs | 8 - .../parser/no-const-fn-in-extern-block.stderr | 14 - src/test/ui/parser/pat-lt-bracket-2.stderr | 6 - src/test/ui/parser/pat-tuple-4.rs | 1 + src/test/ui/parser/pat-tuple-4.stderr | 16 +- src/test/ui/parser/pat-tuple-5.stderr | 4 +- .../ui/parser/recover-from-bad-variant.stderr | 3 - .../require-parens-for-chained-comparison.rs | 21 +- ...quire-parens-for-chained-comparison.stderr | 30 +- src/test/ui/partialeq_help.stderr | 1 + src/test/ui/pattern/rest-pat-syntactic.rs | 2 - src/test/ui/phantom-oibit.stderr | 8 +- src/test/ui/precise_pointer_size_matching.rs | 2 +- src/test/ui/privacy/privacy-ns1.stderr | 2 +- src/test/ui/privacy/privacy-ns2.stderr | 2 +- src/test/ui/privacy/privacy5.rs | 104 +- src/test/ui/privacy/privacy5.stderr | 344 ++- .../auxiliary/gen-macro-rules-hygiene.rs | 23 - .../proc-macro/auxiliary/mixed-site-span.rs | 42 - .../ui/proc-macro/auxiliary/more-gates.rs | 35 + .../proc-macro/auxiliary/test-macros-rpass.rs | 26 + .../ui/proc-macro/disappearing-resolution.rs | 22 - .../proc-macro/disappearing-resolution.stderr | 15 - .../ui/proc-macro/dollar-crate-issue-62325.rs | 2 + .../dollar-crate-issue-62325.stdout | 22 +- src/test/ui/proc-macro/dollar-crate.stdout | 48 +- src/test/ui/proc-macro/expand-with-a-macro.rs | 2 +- .../ui/proc-macro/gen-macro-rules-hygiene.rs | 23 - .../proc-macro/gen-macro-rules-hygiene.stderr | 28 - .../ui/proc-macro/invalid-punct-ident-1.rs | 1 - .../proc-macro/invalid-punct-ident-1.stderr | 2 +- .../ui/proc-macro/invalid-punct-ident-2.rs | 1 - .../proc-macro/invalid-punct-ident-2.stderr | 2 +- .../ui/proc-macro/invalid-punct-ident-3.rs | 1 - .../proc-macro/invalid-punct-ident-3.stderr | 2 +- src/test/ui/proc-macro/lifetimes.rs | 2 + src/test/ui/proc-macro/lifetimes.stderr | 2 +- .../ui/proc-macro/macros-in-extern-derive.rs | 6 - .../proc-macro/macros-in-extern-derive.stderr | 8 - .../ui/proc-macro/macros-in-extern-rpass.rs | 25 + src/test/ui/proc-macro/macros-in-type.rs | 11 - src/test/ui/proc-macro/mixed-site-span.rs | 26 - src/test/ui/proc-macro/mixed-site-span.stderr | 49 - src/test/ui/proc-macro/more-gates.rs | 22 + src/test/ui/proc-macro/more-gates.stderr | 48 + .../proc-macro/proc-macro-deprecated-attr.rs | 16 - src/test/ui/proc-macro/proc-macro-gates.rs | 1 + .../ui/proc-macro/proc-macro-gates.stderr | 21 +- .../ui/qualified/qualified-path-params.stderr | 3 +- src/test/ui/reachable-unnameable-items.rs | 2 +- ...recursive-types-are-not-uninhabited.stderr | 7 - src/test/ui/refutable-pattern-errors.stderr | 7 - ...unds-on-objects-and-type-parameters.stderr | 6 +- ...region-invariant-static-error-reporting.rs | 2 +- ...on-invariant-static-error-reporting.stderr | 2 +- .../regions/region-object-lifetime-2.stderr | 5 +- .../regions/region-object-lifetime-4.stderr | 5 +- .../region-object-lifetime-in-coercion.stderr | 7 +- .../ui/regions/regions-addr-of-self.stderr | 1 - .../regions/regions-addr-of-upvar-self.stderr | 3 +- ...pertrait-outlives-container.migrate.stderr | 4 +- ...-type-region-bound-in-trait-not-met.stderr | 7 +- ...-type-static-bound-in-trait-not-met.stderr | 3 +- src/test/ui/regions/regions-bounds.stderr | 8 +- .../regions-close-object-into-object-2.stderr | 3 +- .../regions-close-object-into-object-4.stderr | 3 +- ...-close-over-type-parameter-multiple.stderr | 5 +- .../ui/regions/regions-creating-enums4.stderr | 5 +- .../regions-early-bound-error-method.stderr | 4 +- .../regions/regions-early-bound-error.stderr | 4 +- .../ui/regions/regions-escape-method.stderr | 1 - .../regions-escape-via-trait-or-not.stderr | 1 - ...gions-free-region-ordering-callee-4.stderr | 4 +- ...ions-free-region-ordering-incorrect.stderr | 5 +- ...-implied-bounds-projection-gap-hr-1.stderr | 4 +- .../ui/regions/regions-infer-call-3.stderr | 1 - ...egions-infer-invariance-due-to-decl.stderr | 2 +- ...nfer-invariance-due-to-mutability-3.stderr | 2 +- ...nfer-invariance-due-to-mutability-4.stderr | 2 +- .../ui/regions/regions-infer-not-param.stderr | 12 +- .../regions-infer-paramd-indirect.stderr | 2 +- src/test/ui/regions/regions-nested-fns.stderr | 5 +- ...ions-normalize-in-where-clause-list.stderr | 5 +- ...s-projection-container-hrtb.migrate.stderr | 8 +- ...ves-projection-container-wc.migrate.stderr | 4 +- ...gions-outlives-projection-container.stderr | 16 +- .../ui/regions/regions-ret-borrowed-1.stderr | 3 +- .../ui/regions/regions-ret-borrowed.stderr | 3 +- ...ons-return-ref-to-upvar-issue-17403.stderr | 3 +- .../regions-static-bound.migrate.stderr | 2 +- src/test/ui/regions/regions-trait-1.stderr | 2 +- .../regions-trait-object-subtyping.stderr | 14 +- ...ns-variance-invariant-use-covariant.stderr | 2 +- .../ui/regions/regions-wf-trait-object.stderr | 4 +- .../ui/reject-specialized-drops-8142.stderr | 8 +- .../ui/repr/repr-packed-contains-align.stderr | 1 - src/test/ui/resolve/issue-16058.stderr | 1 - src/test/ui/resolve/issue-18252.stderr | 3 - src/test/ui/resolve/issue-19452.stderr | 3 - src/test/ui/resolve/issue-21221-1.stderr | 2 +- src/test/ui/resolve/issue-2356.stderr | 18 +- src/test/ui/resolve/issue-39226.stderr | 3 - ...sue-65025-extern-static-parent-generics.rs | 10 - ...65025-extern-static-parent-generics.stderr | 12 - ...issue-65035-static-with-parent-generics.rs | 29 - ...e-65035-static-with-parent-generics.stderr | 53 - src/test/ui/resolve/issue-6702.stderr | 9 +- src/test/ui/resolve/levenshtein.stderr | 4 +- src/test/ui/resolve/privacy-enum-ctor.stderr | 36 +- src/test/ui/resolve/privacy-struct-ctor.rs | 12 +- .../ui/resolve/privacy-struct-ctor.stderr | 51 +- .../termination-trait-in-test.rs | 2 - .../auxiliary/enums.rs | 1 + .../auxiliary/structs.rs | 2 + .../auxiliary/variants.rs | 1 + .../enum_same_crate.rs | 2 + .../improper_ctypes/auxiliary/types.rs | 29 - .../improper_ctypes/extern_crate_improper.rs | 24 - .../extern_crate_improper.stderr | 47 - .../improper_ctypes/same_crate_proper.rs | 45 - .../invalid-attribute.rs | 2 + .../invalid-attribute.stderr | 6 +- src/test/ui/rfc-2008-non-exhaustive/struct.rs | 2 +- .../ui/rfc-2008-non-exhaustive/struct.stderr | 7 +- .../structs_same_crate.rs | 1 + .../uninhabited/auxiliary/uninhabited.rs | 1 + .../uninhabited/coercions_same_crate.rs | 1 + .../uninhabited/coercions_same_crate.stderr | 8 +- .../uninhabited/indirect_match_same_crate.rs | 1 + .../indirect_match_same_crate.stderr | 8 +- ...tch_with_exhaustive_patterns_same_crate.rs | 1 + .../issue-65157-repeated-match-arm.rs | 21 - .../issue-65157-repeated-match-arm.stderr | 14 - .../uninhabited/match_same_crate.rs | 1 + .../uninhabited/match_same_crate.stderr | 6 +- ...tch_with_exhaustive_patterns_same_crate.rs | 1 + .../uninhabited/patterns_same_crate.rs | 1 + .../uninhabited/patterns_same_crate.stderr | 10 +- .../ui/rfc-2008-non-exhaustive/variant.stderr | 6 + .../variants_same_crate.rs | 2 + .../downcast-unsafe-trait-objects.rs | 23 - .../manual-self-impl-for-unsafe-obj.rs | 69 - .../static-dispatch-unsafe-object.rs | 37 - .../rfc-2091-track-caller/error-odd-syntax.rs | 7 - .../error-odd-syntax.stderr | 16 - .../error-with-invalid-abi.rs | 7 - .../error-with-invalid-abi.stderr | 17 - .../rfc-2091-track-caller/error-with-naked.rs | 8 - .../error-with-naked.stderr | 17 - .../error-with-trait-decl.rs | 13 - .../error-with-trait-decl.stderr | 17 - .../error-with-trait-default-impl.rs | 9 - .../error-with-trait-default-impl.stderr | 17 - .../error-with-trait-fn-impl.rs | 13 - .../error-with-trait-fn-impl.stderr | 17 - .../ui/rfc-2091-track-caller/only-for-fns.rs | 7 - .../rfc-2091-track-caller/only-for-fns.stderr | 18 - src/test/ui/rfc-2091-track-caller/pass.rs | 9 - src/test/ui/rfc-2091-track-caller/pass.stderr | 8 - .../rfc-2093-infer-outlives/explicit-union.rs | 5 +- .../explicit-union.stderr | 4 +- .../rfc-2093-infer-outlives/nested-union.rs | 5 +- .../nested-union.stderr | 4 +- ...ns-outlives-nominal-type-region-rev.stderr | 4 +- ...egions-outlives-nominal-type-region.stderr | 4 +- ...ions-outlives-nominal-type-type-rev.stderr | 4 +- .../regions-outlives-nominal-type-type.stderr | 4 +- .../regions-struct-not-wf.stderr | 4 +- .../disallowed-positions.stderr | 10 +- .../attr-without-param.rs | 16 - .../attr-without-param.stderr | 20 - .../auxiliary/param-attrs.rs | 12 +- ...-64682-dropping-first-attrs-in-impl-fns.rs | 21 - .../param-attrs-2018.stderr | 4 - .../param-attrs-builtin-attrs.rs | 31 - .../param-attrs-builtin-attrs.stderr | 126 +- .../rfc-2565-param-attrs/param-attrs-cfg.rs | 24 - .../param-attrs-cfg.stderr | 52 +- .../param-attrs-pretty.rs | 6 - .../proc-macro-cannot-be-used.rs | 6 - .../proc-macro-cannot-be-used.stderr | 44 +- .../feature-gate-raw-dylib-2.rs | 8 - .../feature-gate-raw-dylib-2.stderr | 12 - .../feature-gate-raw-dylib.rs | 5 - .../feature-gate-raw-dylib.stderr | 12 - .../link-ordinal-and-name.rs | 12 - .../link-ordinal-and-name.stderr | 16 - .../link-ordinal-invalid-format.rs | 11 - .../link-ordinal-invalid-format.stderr | 18 - .../link-ordinal-too-large.rs | 11 - .../link-ordinal-too-large.stderr | 18 - .../rfc-2005-default-binding-mode/range.rs | 2 +- src/test/ui/rfcs/rfc1857-drop-order.rs | 2 +- .../issue-52202-use-suggestions.stderr | 2 +- .../rust-2018/trait-import-suggestions.stderr | 6 +- src/test/ui/save-analysis/issue-64659.rs | 10 - src/test/ui/save-analysis/issue-65411.rs | 15 - ...ary-self-types-not-object-safe.curr.stderr | 24 - ...bject-safe.object_safe_for_dispatch.stderr | 15 - .../arbitrary-self-types-not-object-safe.rs | 8 +- ...types_pin_lifetime_impl_trait-async.stderr | 4 +- ...pes_pin_lifetime_mismatch-async.nll.stderr | 15 +- ...f_types_pin_lifetime_mismatch-async.stderr | 21 +- .../self/elision/lt-ref-self-async.nll.stderr | 114 +- src/test/ui/self/elision/lt-ref-self-async.rs | 12 +- .../ui/self/elision/lt-ref-self-async.stderr | 54 +- .../elision/ref-mut-self-async.nll.stderr | 114 +- .../ui/self/elision/ref-mut-self-async.rs | 14 +- .../ui/self/elision/ref-mut-self-async.stderr | 54 +- .../elision/ref-mut-struct-async.nll.stderr | 85 +- .../ui/self/elision/ref-mut-struct-async.rs | 10 +- .../self/elision/ref-mut-struct-async.stderr | 45 +- .../ui/self/elision/ref-self-async.nll.stderr | 133 +- src/test/ui/self/elision/ref-self-async.rs | 16 +- .../ui/self/elision/ref-self-async.stderr | 63 +- .../self/elision/ref-struct-async.nll.stderr | 85 +- src/test/ui/self/elision/ref-struct-async.rs | 10 +- .../ui/self/elision/ref-struct-async.stderr | 45 +- src/test/ui/self/self-in-typedefs.rs | 11 +- src/test/ui/self/self_type_keyword.stderr | 2 +- src/test/ui/sepcomp/sepcomp-lib-lto.rs | 1 - .../ui/shadowed/shadowed-trait-methods.stderr | 2 +- src/test/ui/signal-alternate-stack-cleanup.rs | 1 - src/test/ui/span/E0493.stderr | 1 - src/test/ui/span/coerce-suggestions.stderr | 2 +- src/test/ui/span/issue-34264.stderr | 6 - .../auxiliary/cross_crates_defaults.rs | 4 +- .../defaultimpl/specialization-wfcheck.stderr | 6 +- src/test/ui/specialization/issue-36804.rs | 4 - .../specialization/non-defaulted-item-fail.rs | 53 - .../non-defaulted-item-fail.stderr | 81 - .../specialization-default-methods.rs | 5 +- src/test/ui/static/static-closures.stderr | 1 - src/test/ui/static/static-drop-scope.stderr | 3 +- src/test/ui/static/static-lifetime.stderr | 2 +- .../ui/struct-literal-variant-in-if.stderr | 5 +- src/test/ui/structs-enums/rec-align-u64.rs | 3 +- src/test/ui/suggestions/constrain-trait.fixed | 47 - src/test/ui/suggestions/constrain-trait.rs | 47 - .../ui/suggestions/constrain-trait.stderr | 27 - .../fn-or-tuple-struct-without-args.stderr | 3 - .../imm-ref-trait-object-literal.rs | 14 - .../imm-ref-trait-object-literal.stderr | 30 - .../ui/suggestions/imm-ref-trait-object.rs | 8 - .../suggestions/imm-ref-trait-object.stderr | 10 - src/test/ui/suggestions/into-str.stderr | 1 - src/test/ui/suggestions/issue-61226.stderr | 3 - .../ui/suggestions/issue-64252-self-type.rs | 14 - .../suggestions/issue-64252-self-type.stderr | 30 - .../ui/suggestions/match-needing-semi.fixed | 18 - src/test/ui/suggestions/match-needing-semi.rs | 18 - .../ui/suggestions/match-needing-semi.stderr | 36 - .../missing-assoc-type-bound-restriction.rs | 25 - ...issing-assoc-type-bound-restriction.stderr | 43 - .../suggestions/mut-borrow-needed-by-trait.rs | 23 - .../mut-borrow-needed-by-trait.stderr | 41 - src/test/ui/suggestions/remove-as_str.rs | 21 - src/test/ui/suggestions/remove-as_str.stderr | 27 - .../ui/suggestions/restrict-type-argument.rs | 31 - .../suggestions/restrict-type-argument.stderr | 83 - ...oc-fn-call-with-turbofish-through-deref.rs | 13 - ...n-call-with-turbofish-through-deref.stderr | 19 - .../suggest-assoc-fn-call-with-turbofish.rs | 11 - ...uggest-assoc-fn-call-with-turbofish.stderr | 22 - src/test/ui/symbol-names/impl1.legacy.stderr | 16 +- src/test/ui/symbol-names/impl1.rs | 20 +- src/test/ui/symbol-names/impl1.v0.stderr | 16 +- src/test/ui/synthetic-param.rs | 6 +- src/test/ui/synthetic-param.stderr | 18 +- .../ui/test-attrs/test-allow-fail-attr.rs | 2 +- .../test-should-fail-good-message.rs | 2 +- src/test/ui/test-panic-abort-disabled.rs | 20 - src/test/ui/test-panic-abort-disabled.stderr | 4 - src/test/ui/test-panic-abort.rs | 37 - src/test/ui/test-panic-abort.run.stdout | 29 - .../tool-attributes-misplaced-1.stderr | 3 +- .../trait-alias/trait-alias-syntax-fail.rs | 3 - .../trait-alias-syntax-fail.stderr | 22 +- .../traits/trait-alias/trait-alias-wf.stderr | 7 +- .../traits/trait-as-struct-constructor.stderr | 1 - .../trait-bounds-on-structs-and-enums.stderr | 14 +- .../ui/traits/trait-impl-for-module.stderr | 1 - ...trait-has-wrong-lifetime-parameters.stderr | 5 +- src/test/ui/traits/trait-item-privacy.stderr | 6 +- .../ui/traits/trait-matching-lifetimes.stderr | 8 +- .../ui/traits/trait-method-private.stderr | 2 +- src/test/ui/traits/trait-object-safety.stderr | 1 - .../traits/trait-suggest-where-clause.stderr | 10 +- src/test/ui/traits/trait-test-2.stderr | 1 - ...inductive-overflow-supertrait-oibit.stderr | 3 +- .../traits-repeated-supertrait-ambig.stderr | 8 +- .../try-block/try-block-in-edition2015.stderr | 1 - .../try-block-unreachable-code-lint.rs | 76 - .../try-block-unreachable-code-lint.stderr | 38 - src/test/ui/{never_type => }/try_from.rs | 0 ...riant-form-through-Self-issue-58006.stderr | 1 - ...t-variant-form-through-alias-caught.stderr | 2 +- .../generic_underconstrained.stderr | 4 +- .../generic_underconstrained2.stderr | 8 +- ...sue-65679-inst-opaque-ty-from-val-twice.rs | 17 - .../type/type-ascription-with-fn-call.stderr | 1 - src/test/ui/type/type-check-defaults.stderr | 7 +- .../type-params-in-different-spaces-2.stderr | 8 +- .../ui/type/type-path-err-node-types.stderr | 2 +- .../typeck-auto-trait-no-supertraits-2.stderr | 1 - .../typeck-auto-trait-no-supertraits.stderr | 1 - ...typeck-default-trait-impl-assoc-type.fixed | 17 - .../typeck-default-trait-impl-assoc-type.rs | 2 - ...ypeck-default-trait-impl-assoc-type.stderr | 5 +- ...ypeck-default-trait-impl-send-param.stderr | 3 +- .../ui/ufcs/ufcs-explicit-self-bad.stderr | 8 +- .../ui/ufcs/ufcs-partially-resolved.stderr | 2 +- ...ures-failed-recursive-fn-1.polonius.stderr | 60 + .../unboxed-closures-unique-type-id.rs | 1 - src/test/ui/underscore-imports/hygiene-2.rs | 33 - src/test/ui/underscore-imports/hygiene.rs | 40 - src/test/ui/underscore-imports/hygiene.stderr | 27 - .../ui/underscore-imports/macro-expanded.rs | 45 - src/test/ui/underscore-imports/shadow.stderr | 2 +- .../dyn-trait-underscore.stderr | 1 - .../uninhabited-irrefutable.stderr | 7 - .../uninhabited-matches-feature-gated.stderr | 7 - src/test/ui/union/issue-41073.rs | 24 - src/test/ui/union/issue-41073.stderr | 15 - .../union/union-borrow-move-parent-sibling.rs | 61 +- .../union-borrow-move-parent-sibling.stderr | 34 +- src/test/ui/union/union-custom-drop.rs | 19 - src/test/ui/union/union-custom-drop.stderr | 15 - src/test/ui/union/union-derive-clone.rs | 13 +- src/test/ui/union/union-derive-clone.stderr | 12 +- src/test/ui/union/union-derive-rpass.rs | 5 +- src/test/ui/union/union-drop-assign.rs | 11 +- src/test/ui/union/union-drop.rs | 11 +- src/test/ui/union/union-generic-rpass.rs | 18 +- src/test/ui/union/union-manuallydrop-rpass.rs | 42 - src/test/ui/union/union-nodrop.rs | 15 +- src/test/ui/union/union-overwrite.rs | 14 +- src/test/ui/union/union-sized-field.stderr | 9 +- src/test/ui/union/union-unsafe.rs | 34 +- src/test/ui/union/union-unsafe.stderr | 66 +- .../union-with-drop-fields-lint-rpass.rs | 32 + ...elds.rs => union-with-drop-fields-lint.rs} | 7 +- .../union/union-with-drop-fields-lint.stderr | 26 + .../ui/union/union-with-drop-fields.stderr | 39 - .../auxiliary/unreachable_variant.rs | 0 .../unreachable-arm.rs | 0 .../unreachable-arm.stderr | 0 .../unreachable-code.rs | 0 .../unreachable-code.stderr | 0 .../unreachable-in-call.rs | 0 .../unreachable-in-call.stderr | 0 .../unreachable-loop-patterns.rs | 2 + .../unreachable-loop-patterns.stderr | 6 +- .../unreachable-try-pattern.rs | 2 +- .../unreachable-try-pattern.stderr | 0 .../unreachable-variant.rs | 0 .../unreachable-variant.stderr | 0 .../unwarned-match-on-never.rs | 0 .../unwarned-match-on-never.stderr | 0 .../ui/unsized/unsized-bare-typaram.stderr | 5 +- src/test/ui/unsized/unsized-enum.stderr | 5 +- src/test/ui/unsized/unsized-enum2.stderr | 16 +- .../unsized-inherent-impl-self-type.stderr | 5 +- src/test/ui/unsized/unsized-struct.stderr | 10 +- .../unsized-trait-impl-self-type.stderr | 5 +- .../unsized-trait-impl-trait-arg.stderr | 5 +- src/test/ui/unsized3.stderr | 18 +- src/test/ui/unsized5.stderr | 13 +- src/test/ui/unsized6.stderr | 51 +- src/test/ui/unsized7.stderr | 5 +- src/test/ui/use/issue-18986.stderr | 1 - src/test/ui/use/use-meta-mismatch.rs | 2 +- src/test/ui/use/use-meta-mismatch.stderr | 2 +- .../variance-btree-invariant-types.stderr | 24 +- .../variance-contravariant-arg-object.stderr | 8 +- ...iance-contravariant-arg-trait-match.stderr | 8 +- ...ance-contravariant-self-trait-match.stderr | 8 +- .../variance-covariant-arg-object.stderr | 8 +- .../variance-covariant-arg-trait-match.stderr | 8 +- ...variance-covariant-self-trait-match.stderr | 8 +- .../variance-invariant-arg-object.stderr | 8 +- .../variance-invariant-arg-trait-match.stderr | 8 +- ...variance-invariant-self-trait-match.stderr | 8 +- .../variance-regions-unused-direct.stderr | 4 +- .../variance-regions-unused-indirect.stderr | 4 +- .../variance-unused-region-param.stderr | 4 +- .../variance-unused-type-param.stderr | 6 +- ...variance-use-contravariant-struct-1.stderr | 4 +- .../variance-use-covariant-struct-1.stderr | 4 +- .../variance-use-invariant-struct-1.stderr | 8 +- .../ui/variants/variant-used-as-type.stderr | 1 - src/test/ui/wf/issue-48638.rs | 21 - .../ui/wf/wf-convert-unsafe-trait-obj-box.rs | 18 - .../wf/wf-convert-unsafe-trait-obj-box.stderr | 33 - src/test/ui/wf/wf-convert-unsafe-trait-obj.rs | 18 - .../ui/wf/wf-convert-unsafe-trait-obj.stderr | 33 - src/test/ui/wf/wf-enum-bound.stderr | 3 +- .../wf/wf-enum-fields-struct-variant.stderr | 5 +- src/test/ui/wf/wf-enum-fields.stderr | 4 +- src/test/ui/wf/wf-fn-where-clause.stderr | 7 +- .../wf/wf-impl-associated-type-trait.stderr | 4 +- src/test/ui/wf/wf-in-fn-arg.stderr | 7 +- src/test/ui/wf/wf-in-fn-ret.stderr | 7 +- src/test/ui/wf/wf-in-fn-type-arg.stderr | 5 +- src/test/ui/wf/wf-in-fn-type-ret.stderr | 5 +- src/test/ui/wf/wf-in-fn-where-clause.stderr | 3 +- src/test/ui/wf/wf-in-obj-type-trait.stderr | 5 +- ...f-inherent-impl-method-where-clause.stderr | 4 +- .../wf/wf-inherent-impl-where-clause.stderr | 7 +- src/test/ui/wf/wf-static-method.stderr | 22 +- src/test/ui/wf/wf-struct-bound.stderr | 3 +- src/test/ui/wf/wf-struct-field.stderr | 4 +- .../wf/wf-trait-associated-type-bound.stderr | 7 +- .../wf/wf-trait-associated-type-trait.stderr | 7 +- src/test/ui/wf/wf-trait-bound.stderr | 3 +- src/test/ui/wf/wf-trait-default-fn-arg.stderr | 7 +- src/test/ui/wf/wf-trait-default-fn-ret.stderr | 7 +- .../wf-trait-default-fn-where-clause.stderr | 7 +- src/test/ui/wf/wf-trait-fn-arg.stderr | 7 +- src/test/ui/wf/wf-trait-fn-ret.stderr | 7 +- .../ui/wf/wf-trait-fn-where-clause.stderr | 7 +- src/test/ui/wf/wf-trait-superbound.stderr | 7 +- src/test/ui/wf/wf-unsafe-trait-obj-match.rs | 29 - .../ui/wf/wf-unsafe-trait-obj-match.stderr | 38 - ...traints-are-local-for-inherent-impl.stderr | 5 +- ...onstraints-are-local-for-trait-impl.stderr | 5 +- src/tools/build-manifest/src/main.rs | 30 - src/tools/cargo | 2 +- src/tools/clippy | 2 +- src/tools/compiletest/src/common.rs | 2 - src/tools/compiletest/src/header.rs | 10 +- src/tools/compiletest/src/runtest.rs | 22 +- src/tools/error_index_generator/build.rs | 2 +- src/tools/linkchecker/main.rs | 1 + src/tools/miri | 2 +- src/tools/publish_toolstate.py | 2 +- src/tools/rls | 2 +- src/tools/rustc-workspace-hack/Cargo.toml | 1 - src/tools/rustfmt | 2 +- src/tools/tidy/src/debug_artifacts.rs | 24 - src/tools/tidy/src/deps.rs | 1 - src/tools/tidy/src/error_codes_check.rs | 137 -- src/tools/tidy/src/lib.rs | 6 +- src/tools/tidy/src/main.rs | 2 - triagebot.toml | 14 +- 2032 files changed, 27656 insertions(+), 36900 deletions(-) create mode 100644 src/ci/docker/asmjs/Dockerfile delete mode 100644 src/ci/docker/disabled/asmjs/Dockerfile create mode 100644 src/ci/docker/disabled/wasm32-exp/Dockerfile create mode 100755 src/ci/docker/disabled/wasm32-exp/node.sh create mode 100644 src/ci/docker/disabled/wasm32/Dockerfile delete mode 100644 src/ci/docker/dist-armv7-linux/crosstool-ng.sh create 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/ci/docker/scripts/emscripten-wasm.sh delete mode 100644 src/ci/docker/wasm32/Dockerfile delete mode 100644 src/doc/rustc/src/json.md delete mode 100644 src/doc/rustc/src/targets/known-issues.md delete mode 100644 src/doc/unstable-book/src/compiler-flags/report-time.md create mode 100644 src/doc/unstable-book/src/language-features/non-exhaustive.md delete mode 100644 src/doc/unstable-book/src/language-features/track-caller.md create mode 100644 src/grammar/.gitignore create mode 100644 src/grammar/lexer.l create mode 100644 src/grammar/parser-lalr-main.c create mode 100644 src/grammar/parser-lalr.y create mode 100644 src/grammar/raw-string-literal-ambiguity.md create mode 100755 src/grammar/testparser.py create mode 100644 src/grammar/tokens.h delete mode 100644 src/liballoc/tests/boxed.rs rename src/libcore/{array/mod.rs => array.rs} (98%) delete mode 100644 src/libcore/array/iter.rs rename src/{librustc_passes => librustc/middle}/dead.rs (98%) rename src/{librustc_passes => librustc/middle}/entry.rs (95%) rename src/{librustc_passes => librustc/middle}/intrinsicck.rs (94%) rename src/{librustc_passes => librustc/middle}/liveness.rs (99%) rename src/{librustc_interface => librustc/session/config}/tests.rs (92%) create mode 100644 src/librustc_codegen_llvm/error_codes.rs create mode 100644 src/librustc_codegen_ssa/callee.rs rename src/{librustc_index => librustc_data_structures}/bit_set.rs (94%) rename src/{librustc_index => librustc_data_structures}/bit_set/tests.rs (100%) rename src/{librustc_index/vec.rs => librustc_data_structures/indexed_vec.rs} (100%) delete mode 100644 src/librustc_index/Cargo.toml delete mode 100644 src/librustc_index/lib.rs create mode 100644 src/librustc_interface/profile/mod.rs create mode 100644 src/librustc_interface/profile/trace.rs create mode 100644 src/librustc_metadata/index.rs delete mode 100644 src/librustc_metadata/table.rs delete mode 100644 src/librustc_mir/dataflow/generic/graphviz.rs create mode 100644 src/librustc_mir/monomorphize/item.rs create mode 100644 src/librustc_passes/rvalue_promotion.rs create mode 100644 src/librustc_target/abi/call/asmjs.rs delete mode 100644 src/librustc_target/abi/call/wasm32_bindgen_compat.rs delete mode 100644 src/librustc_target/spec/aarch64_unknown_none_softfloat.rs create mode 100644 src/librustc_target/spec/wasm32_experimental_emscripten.rs rename src/{libsyntax_expand => libsyntax/ext}/allocator.rs (96%) rename src/{libsyntax_expand => libsyntax/ext}/base.rs (96%) rename src/{libsyntax_expand => libsyntax/ext}/build.rs (98%) rename src/{libsyntax_expand => libsyntax/ext}/expand.rs (87%) rename src/{libsyntax_expand => libsyntax/ext}/mbe.rs (96%) rename src/{libsyntax_expand => libsyntax/ext}/mbe/macro_check.rs (98%) rename src/{libsyntax_expand => libsyntax/ext}/mbe/macro_parser.rs (95%) rename src/{libsyntax_expand => libsyntax/ext}/mbe/macro_rules.rs (95%) rename src/{libsyntax_expand => libsyntax/ext}/mbe/quoted.rs (97%) rename src/{libsyntax_expand => libsyntax/ext}/mbe/transcribe.rs (97%) rename src/{libsyntax_expand => libsyntax/ext}/placeholders.rs (92%) rename src/{libsyntax_expand => libsyntax/ext}/proc_macro.rs (86%) rename src/{libsyntax_expand => libsyntax/ext}/proc_macro_server.rs (96%) delete mode 100644 src/libsyntax/json/tests.rs rename src/libsyntax/parse/{parser => }/attr.rs (83%) rename src/libsyntax/parse/{parser => }/diagnostics.rs (81%) delete mode 100644 src/libsyntax/sess.rs delete mode 100644 src/libsyntax_expand/Cargo.toml delete mode 100644 src/libsyntax_expand/lib.rs delete mode 100644 src/libsyntax_ext/util.rs delete mode 100644 src/libtest/bench.rs delete mode 100644 src/libtest/cli.rs delete mode 100644 src/libtest/console.rs delete mode 100644 src/libtest/event.rs delete mode 100644 src/libtest/helpers/concurrency.rs delete mode 100644 src/libtest/helpers/exit_code.rs delete mode 100644 src/libtest/helpers/isatty.rs delete mode 100644 src/libtest/helpers/metrics.rs delete mode 100644 src/libtest/helpers/mod.rs delete mode 100644 src/libtest/helpers/sink.rs delete mode 100644 src/libtest/options.rs delete mode 100644 src/libtest/test_result.rs delete mode 100644 src/libtest/time.rs delete mode 100644 src/libtest/types.rs create mode 160000 src/llvm-emscripten create mode 100644 src/test/codegen/extern-functions.rs delete mode 100644 src/test/codegen/non-terminate/infinite-loop-1.rs delete mode 100644 src/test/codegen/non-terminate/infinite-loop-2.rs delete mode 100644 src/test/codegen/non-terminate/infinite-recursion.rs create mode 100644 src/test/codegen/nounwind-extern.rs delete mode 100644 src/test/codegen/unwind-extern-exports.rs delete mode 100644 src/test/codegen/unwind-extern-imports.rs delete mode 100644 src/test/incremental/const-generics/issue-61338.rs delete mode 100644 src/test/incremental/const-generics/issue-61516.rs delete mode 100644 src/test/incremental/const-generics/issue-62536.rs delete mode 100644 src/test/incremental/const-generics/issue-64087.rs delete mode 100644 src/test/incremental/const-generics/issue-65623.rs delete mode 100644 src/test/mir-opt/const_prop/aggregate.rs delete mode 100644 src/test/mir-opt/const_prop/boxes.rs delete mode 100644 src/test/mir-opt/const_prop/discriminant.rs delete mode 100644 src/test/mir-opt/const_prop/repeat.rs delete mode 100644 src/test/mir-opt/simplify-locals-removes-unused-consts.rs rename src/test/{ui/never_type => run-fail}/adjust_never.rs (93%) rename src/test/{ui/never_type => run-fail}/call-fn-never-arg.rs (94%) rename src/test/{ui/never_type => run-fail}/cast-never.rs (93%) rename src/test/{ui/never_type => run-fail}/never-associated-type.rs (96%) rename src/test/{ui/never_type => run-fail}/never-type-arg.rs (95%) create mode 100644 src/test/run-make-fulldeps/linker-output-non-utf8/Makefile create mode 100644 src/test/run-make-fulldeps/linker-output-non-utf8/exec.rs create mode 100644 src/test/run-make-fulldeps/linker-output-non-utf8/library.rs delete mode 100644 src/test/run-make-fulldeps/sanitizer-staticlib-link/program.rs delete mode 100644 src/test/rustdoc-ui/doc-test-doctest-feature.rs delete mode 100644 src/test/rustdoc-ui/doc-test-doctest-feature.stdout delete mode 100644 src/test/rustdoc-ui/doc-test-rustdoc-feature.rs delete mode 100644 src/test/rustdoc-ui/doc-test-rustdoc-feature.stdout delete mode 100644 src/test/rustdoc/macro-in-closure.rs delete mode 100644 src/test/rustdoc/sanitizer-option.rs delete mode 100644 src/test/ui-fulldeps/issue-15778-pass.stderr delete mode 100644 src/test/ui-fulldeps/issue-40001.stderr delete mode 100644 src/test/ui-fulldeps/llvm-pass-plugin.stderr delete mode 100644 src/test/ui-fulldeps/lto-syntax-extension.stderr delete mode 100644 src/test/ui-fulldeps/outlive-expansion-phase.stderr delete mode 100644 src/test/ui-fulldeps/plugin-args-1.stderr delete mode 100644 src/test/ui-fulldeps/plugin-args-2.stderr delete mode 100644 src/test/ui-fulldeps/plugin-args-3.stderr delete mode 100644 src/test/ui-fulldeps/roman-numerals-macro.stderr rename src/test/ui/{panics/abort-on-panic.rs => abi/abort-on-c-abi.rs} (50%) rename src/test/ui/{ => abi}/macros/macros-in-extern.rs (60%) create mode 100644 src/test/ui/abi/macros/macros-in-extern.stderr create mode 100644 src/test/ui/abi/proc-macro/auxiliary/test-macros.rs rename src/test/ui/{ => abi}/proc-macro/macros-in-extern.rs (62%) create mode 100644 src/test/ui/abi/proc-macro/macros-in-extern.stderr rename src/test/ui/{uninhabited => }/always-inhabited-union-ref.rs (100%) rename src/test/ui/{uninhabited => }/always-inhabited-union-ref.stderr (100%) delete mode 100644 src/test/ui/asm/issue-51431.rs delete mode 100644 src/test/ui/asm/issue-51431.stderr delete mode 100644 src/test/ui/associated-const/issue-63496.rs delete mode 100644 src/test/ui/associated-const/issue-63496.stderr delete mode 100644 src/test/ui/associated-item/issue-48027.rs delete mode 100644 src/test/ui/associated-item/issue-48027.stderr delete mode 100644 src/test/ui/associated-types/associated-types-bound-failure.fixed delete mode 100644 src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed delete mode 100644 src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed delete mode 100644 src/test/ui/associated-types/associated-types-unsized.fixed delete mode 100644 src/test/ui/associated-types/issue-44153.rs delete mode 100644 src/test/ui/associated-types/issue-44153.stderr delete mode 100644 src/test/ui/associated-types/issue-48010.rs delete mode 100644 src/test/ui/associated-types/issue-64855-2.rs delete mode 100644 src/test/ui/associated-types/issue-64855.rs delete mode 100644 src/test/ui/associated-types/issue-64855.stderr delete mode 100644 src/test/ui/async-await/async-assoc-fn-anon-lifetimes.rs delete mode 100644 src/test/ui/async-await/async-borrowck-escaping-block-error.fixed delete mode 100644 src/test/ui/async-await/async-borrowck-escaping-block-error.rs delete mode 100644 src/test/ui/async-await/async-borrowck-escaping-block-error.stderr create mode 100644 src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr delete mode 100644 src/test/ui/async-await/async-fn-size-uninit-locals.rs delete mode 100644 src/test/ui/async-await/issue-64130-non-send-future-diags.rs delete mode 100644 src/test/ui/async-await/issue-64130-non-send-future-diags.stderr delete mode 100644 src/test/ui/async-await/issues/issue-64964.rs delete mode 100644 src/test/ui/async-await/issues/issue-65159.rs delete mode 100644 src/test/ui/async-await/issues/issue-65159.stderr delete mode 100644 src/test/ui/async-await/return-ty-raw-ptr-coercion.rs delete mode 100644 src/test/ui/async-await/return-ty-unsize-coercion.rs delete mode 100644 src/test/ui/async-await/unreachable-lint-1.rs delete mode 100644 src/test/ui/async-await/unreachable-lint-1.stderr delete mode 100644 src/test/ui/async-await/unreachable-lint.rs delete mode 100644 src/test/ui/async-await/unused-lifetime.rs delete mode 100644 src/test/ui/async-await/unused-lifetime.stderr create mode 100644 src/test/ui/borrowck/borrowck-escaping-closure-error-2.polonius.stderr delete mode 100644 src/test/ui/borrowck/issue-64453.rs delete mode 100644 src/test/ui/borrowck/issue-64453.stderr create mode 100644 src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.polonius.stderr create mode 100644 src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr create mode 100644 src/test/ui/borrowck/two-phase-surprise-no-conflict.polonius.stderr rename src/test/ui/{never_type => }/call-fn-never-arg-wrong-type.rs (100%) rename src/test/ui/{never_type => }/call-fn-never-arg-wrong-type.stderr (100%) delete mode 100644 src/test/ui/closures/issue-41366.rs delete mode 100644 src/test/ui/closures/issue-41366.stderr delete mode 100644 src/test/ui/closures/issue-52437.rs delete mode 100644 src/test/ui/closures/issue-52437.stderr delete mode 100644 src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs delete mode 100644 src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr delete mode 100644 src/test/ui/coherence/impl-foreign-for-foreign.rs delete mode 100644 src/test/ui/coherence/impl-foreign-for-foreign.stderr delete mode 100644 src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs delete mode 100644 src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr delete mode 100644 src/test/ui/coherence/impl-foreign-for-foreign[local].rs delete mode 100644 src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs delete mode 100644 src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr delete mode 100644 src/test/ui/coherence/impl-foreign-for-fundamental[local].rs delete mode 100644 src/test/ui/coherence/impl-foreign-for-local.rs delete mode 100644 src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs delete mode 100644 src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr delete mode 100644 src/test/ui/coherence/impl-foreign[foreign]-for-local.rs delete mode 100644 src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs delete mode 100644 src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr delete mode 100644 src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr delete mode 100644 src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr delete mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr delete mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr delete mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr delete mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr delete mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr delete mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr delete mode 100644 src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr delete mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr delete mode 100644 src/test/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr delete mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr delete mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs delete mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr create mode 100644 src/test/ui/coherence/re-rebalance-coherence-rpass.rs delete mode 100644 src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs delete mode 100644 src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.rs delete mode 100644 src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr delete mode 100644 src/test/ui/const-generics/auxiliary/const_generic_lib.rs delete mode 100644 src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs delete mode 100644 src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr delete mode 100644 src/test/ui/const-generics/const-argument-cross-crate.rs delete mode 100644 src/test/ui/const-generics/fn-const-param-call.rs delete mode 100644 src/test/ui/const-generics/fn-const-param-call.stderr delete mode 100644 src/test/ui/const-generics/fn-const-param-infer.rs delete mode 100644 src/test/ui/const-generics/fn-const-param-infer.stderr delete mode 100644 src/test/ui/const-generics/forbid-non-structural_match-types.rs delete mode 100644 src/test/ui/const-generics/forbid-non-structural_match-types.stderr rename src/test/ui/const-generics/{issues => }/issue-60263.rs (100%) rename src/test/ui/const-generics/{issues => }/issue-60263.stderr (86%) rename src/test/ui/const-generics/{issues => }/issue-60818-struct-constructors.rs (100%) rename src/test/ui/const-generics/{issues => }/issue-60818-struct-constructors.stderr (100%) rename src/test/ui/const-generics/{issues => }/issue-61336-1.rs (100%) rename src/test/ui/const-generics/{issues => }/issue-61336-1.stderr (100%) rename src/test/ui/const-generics/{issues => }/issue-61336-2.rs (100%) rename src/test/ui/const-generics/{issues => }/issue-61336-2.stderr (100%) rename src/test/ui/const-generics/{issues => }/issue-61336.rs (100%) rename src/test/ui/const-generics/{issues => }/issue-61336.stderr (100%) rename src/test/ui/const-generics/{issues => }/issue-61422.rs (100%) rename src/test/ui/const-generics/{issues => }/issue-61422.stderr (100%) rename src/test/ui/const-generics/{issues => }/issue-61432.rs (100%) rename src/test/ui/const-generics/{issues => }/issue-61432.stderr (100%) rename src/test/ui/const-generics/{issues => }/issue-64519.rs (100%) rename src/test/ui/const-generics/{issues => }/issue-64519.stderr (100%) delete mode 100644 src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs delete mode 100644 src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr delete mode 100644 src/test/ui/const-generics/issues/issue-62579-no-match.rs delete mode 100644 src/test/ui/const-generics/issues/issue-62579-no-match.stderr delete mode 100644 src/test/ui/const-generics/issues/issue-65675.rs delete mode 100644 src/test/ui/const-generics/issues/issue-65675.stderr delete mode 100644 src/test/ui/const-generics/raw-ptr-const-param-deref.rs delete mode 100644 src/test/ui/const-generics/raw-ptr-const-param-deref.stderr delete mode 100644 src/test/ui/const-generics/raw-ptr-const-param.rs delete mode 100644 src/test/ui/const-generics/raw-ptr-const-param.stderr delete mode 100644 src/test/ui/const-generics/slice-const-param-mismatch.rs delete mode 100644 src/test/ui/const-generics/slice-const-param-mismatch.stderr delete mode 100644 src/test/ui/const-generics/slice-const-param.rs delete mode 100644 src/test/ui/const-generics/slice-const-param.stderr delete mode 100644 src/test/ui/const-generics/types-mismatch-const-args.rs delete mode 100644 src/test/ui/const-generics/types-mismatch-const-args.stderr delete mode 100644 src/test/ui/consts/auxiliary/external_macro.rs delete mode 100644 src/test/ui/consts/const-eval/generic-slice.rs delete mode 100644 src/test/ui/consts/const-eval/generic-slice.stderr delete mode 100644 src/test/ui/consts/const-eval/issue-64908.rs delete mode 100644 src/test/ui/consts/const-eval/issue-64970.rs delete mode 100644 src/test/ui/consts/const-eval/issue-64970.stderr delete mode 100644 src/test/ui/consts/const-eval/issue-65394.rs delete mode 100644 src/test/ui/consts/const-eval/issue-65394.stderr delete mode 100644 src/test/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs delete mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs delete mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr delete mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs delete mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr delete mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs delete mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.stderr delete mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn.rs delete mode 100644 src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs delete mode 100644 src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr delete mode 100644 src/test/ui/consts/const-external-macro-const-err.rs delete mode 100644 src/test/ui/consts/const-external-macro-const-err.stderr delete mode 100644 src/test/ui/consts/const-int-pow-rpass.rs delete mode 100644 src/test/ui/consts/issue-64506.rs delete mode 100644 src/test/ui/consts/issue-64662.rs delete mode 100644 src/test/ui/consts/issue-64662.stderr delete mode 100644 src/test/ui/consts/issue-65348.rs delete mode 100644 src/test/ui/consts/miri_unleashed/non_const_fn.rs delete mode 100644 src/test/ui/consts/miri_unleashed/non_const_fn.stderr create mode 100644 src/test/ui/consts/promote_const_let.polonius.stderr rename src/test/ui/{never_type => }/defaulted-never-note.rs (100%) rename src/test/ui/{never_type => }/defaulted-never-note.stderr (100%) rename src/test/ui/{never_type => }/dispatch_from_dyn_zst.rs (100%) rename src/test/ui/{never_type => }/diverging-fallback-control-flow.rs (99%) create mode 100644 src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr delete mode 100644 src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs delete mode 100644 src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-macros_in_extern.rs create mode 100644 src/test/ui/feature-gates/feature-gate-macros_in_extern.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-non_exhaustive.rs create mode 100644 src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-track_caller.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-track_caller.stderr create mode 100644 src/test/ui/generator/ref-escapes-but-not-over-yield.polonius.stderr delete mode 100644 src/test/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.rs delete mode 100644 src/test/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr delete mode 100644 src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs delete mode 100644 src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr delete mode 100644 src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs delete mode 100644 src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr delete mode 100644 src/test/ui/hrtb/due-to-where-clause.nll.stderr rename src/test/ui/{never_type => }/impl-for-never.rs (99%) delete mode 100644 src/test/ui/include-single-expr-helper-1.rs delete mode 100644 src/test/ui/include-single-expr-helper.rs delete mode 100644 src/test/ui/include-single-expr.rs delete mode 100644 src/test/ui/include-single-expr.stderr rename src/test/ui/{issues => }/issue-53912.rs (100%) rename src/test/ui/{issues => }/issue-59020.rs (100%) delete mode 100644 src/test/ui/issues/auxiliary/issue-57271-lib.rs rename src/test/ui/{never_type => issues}/issue-13352.rs (100%) rename src/test/ui/{never_type => issues}/issue-13352.stderr (100%) rename src/test/ui/{never_type => issues}/issue-2149.rs (100%) rename src/test/ui/{never_type => issues}/issue-2149.stderr (100%) rename src/test/ui/{never_type => issues}/issue-44402.rs (90%) delete mode 100644 src/test/ui/issues/issue-47486.rs delete mode 100644 src/test/ui/issues/issue-47486.stderr delete mode 100644 src/test/ui/issues/issue-50571.rs delete mode 100644 src/test/ui/issues/issue-50571.stderr delete mode 100644 src/test/ui/issues/issue-52262.rs delete mode 100644 src/test/ui/issues/issue-52262.stderr delete mode 100644 src/test/ui/issues/issue-57271.rs delete mode 100644 src/test/ui/issues/issue-57271.stderr delete mode 100644 src/test/ui/issues/issue-57399-self-return-impl-trait.rs delete mode 100644 src/test/ui/issues/issue-57399-self-return-impl-trait.stderr delete mode 100644 src/test/ui/issues/issue-58022.rs delete mode 100644 src/test/ui/issues/issue-58022.stderr delete mode 100644 src/test/ui/issues/issue-58344.rs delete mode 100644 src/test/ui/issues/issue-58344.stderr delete mode 100644 src/test/ui/issues/issue-60218.rs delete mode 100644 src/test/ui/issues/issue-60218.stderr delete mode 100644 src/test/ui/issues/issue-64620.rs delete mode 100644 src/test/ui/issues/issue-64620.stderr delete mode 100644 src/test/ui/issues/issue-64792-bad-unicode-ctor.rs delete mode 100644 src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr delete mode 100644 src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs delete mode 100644 src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr delete mode 100644 src/test/ui/issues/issue-65611.rs delete mode 100644 src/test/ui/issues/issue-65611.stderr delete mode 100644 src/test/ui/json-bom-plus-crlf-multifile-aux.rs delete mode 100644 src/test/ui/json-bom-plus-crlf-multifile.rs delete mode 100644 src/test/ui/json-bom-plus-crlf-multifile.stderr delete mode 100644 src/test/ui/json-bom-plus-crlf.rs delete mode 100644 src/test/ui/json-bom-plus-crlf.stderr delete mode 100644 src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr rename src/test/ui/kindck/{kindck-inherited-copy-bound.curr.stderr => kindck-inherited-copy-bound.stderr} (86%) delete mode 100644 src/test/ui/macros/macro-meta-items-modern.rs create mode 100644 src/test/ui/macros/macros-in-extern-rpass.rs delete mode 100644 src/test/ui/mir-dataflow/indirect-mutation-offset.rs delete mode 100644 src/test/ui/mir-dataflow/indirect-mutation-offset.stderr rename src/test/ui/{never_type => }/never-assign-dead-code.rs (82%) rename src/test/ui/{never_type => }/never-assign-dead-code.stderr (92%) rename src/test/ui/{never_type => }/never-assign-wrong-type.rs (100%) rename src/test/ui/{never_type => }/never-assign-wrong-type.stderr (100%) rename src/test/ui/{never_type => }/never-from-impl-is-reserved.rs (100%) rename src/test/ui/{never_type => }/never-from-impl-is-reserved.stderr (100%) rename src/test/ui/{never_type => }/never-result.rs (99%) rename src/test/ui/{never_type => }/never-type-rvalues.rs (100%) rename src/test/ui/{never_type => }/never_coercions.rs (100%) rename src/test/ui/{never_type => }/never_transmute_never.rs (87%) delete mode 100644 src/test/ui/nll/empty-type-predicate-2.rs delete mode 100644 src/test/ui/nll/issue-63154-normalize.rs create mode 100644 src/test/ui/nll/loan_ends_mid_block_pair.polonius.stderr delete mode 100644 src/test/ui/nll/promoted-liveness.rs delete mode 100644 src/test/ui/nll/relate_tys/fn-subtype.rs delete mode 100644 src/test/ui/nll/relate_tys/fn-subtype.stderr delete mode 100644 src/test/ui/nll/relate_tys/trait-hrtb.rs delete mode 100644 src/test/ui/nll/relate_tys/trait-hrtb.stderr create mode 100644 src/test/ui/nll/return-ref-mut-issue-46557.polonius.stderr delete mode 100644 src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr rename src/test/ui/object-safety/{object-safety-associated-consts.curr.stderr => object-safety-associated-consts.stderr} (88%) delete mode 100644 src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr rename src/test/ui/object-safety/{object-safety-generics.curr.stderr => object-safety-generics.stderr} (89%) delete mode 100644 src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr rename src/test/ui/object-safety/{object-safety-mentions-Self.curr.stderr => object-safety-mentions-Self.stderr} (83%) delete mode 100644 src/test/ui/object-safety/object-safety-no-static.curr.stderr delete mode 100644 src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr delete mode 100644 src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr rename src/test/ui/object-safety/{object-safety-sized-2.curr.stderr => object-safety-sized-2.stderr} (89%) delete mode 100644 src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr rename src/test/ui/object-safety/{object-safety-sized.curr.stderr => object-safety-sized.stderr} (90%) delete mode 100644 src/test/ui/or-patterns/issue-64879-trailing-before-guard.rs delete mode 100644 src/test/ui/or-patterns/issue-64879-trailing-before-guard.stderr create mode 100644 src/test/ui/panic-runtime/libtest-unwinds.rs create mode 100644 src/test/ui/panic-runtime/libtest-unwinds.stderr rename src/test/ui/{never_type => }/panic-uninitialized-zeroed.rs (97%) delete mode 100644 src/test/ui/parser/intersection-patterns.rs delete mode 100644 src/test/ui/parser/intersection-patterns.stderr delete mode 100644 src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs delete mode 100644 src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr delete mode 100644 src/test/ui/parser/mismatched-delim-brace-empty-block.rs delete mode 100644 src/test/ui/parser/mismatched-delim-brace-empty-block.stderr delete mode 100644 src/test/ui/parser/no-const-fn-in-extern-block.rs delete mode 100644 src/test/ui/parser/no-const-fn-in-extern-block.stderr delete mode 100644 src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/mixed-site-span.rs create mode 100644 src/test/ui/proc-macro/auxiliary/more-gates.rs create mode 100644 src/test/ui/proc-macro/auxiliary/test-macros-rpass.rs delete mode 100644 src/test/ui/proc-macro/disappearing-resolution.rs delete mode 100644 src/test/ui/proc-macro/disappearing-resolution.stderr delete mode 100644 src/test/ui/proc-macro/gen-macro-rules-hygiene.rs delete mode 100644 src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr delete mode 100644 src/test/ui/proc-macro/macros-in-extern-derive.rs delete mode 100644 src/test/ui/proc-macro/macros-in-extern-derive.stderr create mode 100644 src/test/ui/proc-macro/macros-in-extern-rpass.rs delete mode 100644 src/test/ui/proc-macro/macros-in-type.rs delete mode 100644 src/test/ui/proc-macro/mixed-site-span.rs delete mode 100644 src/test/ui/proc-macro/mixed-site-span.stderr create mode 100644 src/test/ui/proc-macro/more-gates.rs create mode 100644 src/test/ui/proc-macro/more-gates.stderr delete mode 100644 src/test/ui/proc-macro/proc-macro-deprecated-attr.rs delete mode 100644 src/test/ui/resolve/issue-65025-extern-static-parent-generics.rs delete mode 100644 src/test/ui/resolve/issue-65025-extern-static-parent-generics.stderr delete mode 100644 src/test/ui/resolve/issue-65035-static-with-parent-generics.rs delete mode 100644 src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr delete mode 100644 src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs delete mode 100644 src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs delete mode 100644 src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr delete mode 100644 src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs delete mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs delete mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr delete mode 100644 src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs delete mode 100644 src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs delete mode 100644 src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs delete mode 100644 src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs delete mode 100644 src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr delete mode 100644 src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs delete mode 100644 src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr delete mode 100644 src/test/ui/rfc-2091-track-caller/error-with-naked.rs delete mode 100644 src/test/ui/rfc-2091-track-caller/error-with-naked.stderr delete mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs delete mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr delete mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs delete mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr delete mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs delete mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr delete mode 100644 src/test/ui/rfc-2091-track-caller/only-for-fns.rs delete mode 100644 src/test/ui/rfc-2091-track-caller/only-for-fns.stderr delete mode 100644 src/test/ui/rfc-2091-track-caller/pass.rs delete mode 100644 src/test/ui/rfc-2091-track-caller/pass.stderr delete mode 100644 src/test/ui/rfc-2565-param-attrs/attr-without-param.rs delete mode 100644 src/test/ui/rfc-2565-param-attrs/attr-without-param.stderr delete 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-2627-raw-dylib/feature-gate-raw-dylib-2.rs delete mode 100644 src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr delete mode 100644 src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs delete mode 100644 src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr delete mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs delete mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr delete mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs delete mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr delete mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs delete mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr delete mode 100644 src/test/ui/save-analysis/issue-64659.rs delete mode 100644 src/test/ui/save-analysis/issue-65411.rs delete mode 100644 src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr delete mode 100644 src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr delete mode 100644 src/test/ui/specialization/non-defaulted-item-fail.rs delete mode 100644 src/test/ui/specialization/non-defaulted-item-fail.stderr delete mode 100644 src/test/ui/suggestions/constrain-trait.fixed delete mode 100644 src/test/ui/suggestions/constrain-trait.rs delete mode 100644 src/test/ui/suggestions/constrain-trait.stderr delete mode 100644 src/test/ui/suggestions/imm-ref-trait-object-literal.rs delete mode 100644 src/test/ui/suggestions/imm-ref-trait-object-literal.stderr delete mode 100644 src/test/ui/suggestions/imm-ref-trait-object.rs delete mode 100644 src/test/ui/suggestions/imm-ref-trait-object.stderr delete mode 100644 src/test/ui/suggestions/issue-64252-self-type.rs delete mode 100644 src/test/ui/suggestions/issue-64252-self-type.stderr delete mode 100644 src/test/ui/suggestions/match-needing-semi.fixed delete mode 100644 src/test/ui/suggestions/match-needing-semi.rs delete mode 100644 src/test/ui/suggestions/match-needing-semi.stderr delete mode 100644 src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs delete mode 100644 src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr delete mode 100644 src/test/ui/suggestions/mut-borrow-needed-by-trait.rs delete mode 100644 src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr delete mode 100644 src/test/ui/suggestions/remove-as_str.rs delete mode 100644 src/test/ui/suggestions/remove-as_str.stderr delete mode 100644 src/test/ui/suggestions/restrict-type-argument.rs delete mode 100644 src/test/ui/suggestions/restrict-type-argument.stderr delete mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs delete mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr delete mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs delete mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr delete mode 100644 src/test/ui/test-panic-abort-disabled.rs delete mode 100644 src/test/ui/test-panic-abort-disabled.stderr delete mode 100644 src/test/ui/test-panic-abort.rs delete mode 100644 src/test/ui/test-panic-abort.run.stdout delete mode 100644 src/test/ui/try-block/try-block-unreachable-code-lint.rs delete mode 100644 src/test/ui/try-block/try-block-unreachable-code-lint.stderr rename src/test/ui/{never_type => }/try_from.rs (100%) delete mode 100644 src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs delete mode 100644 src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.polonius.stderr delete mode 100644 src/test/ui/underscore-imports/hygiene-2.rs delete mode 100644 src/test/ui/underscore-imports/hygiene.rs delete mode 100644 src/test/ui/underscore-imports/hygiene.stderr delete mode 100644 src/test/ui/underscore-imports/macro-expanded.rs delete mode 100644 src/test/ui/union/issue-41073.rs delete mode 100644 src/test/ui/union/issue-41073.stderr delete mode 100644 src/test/ui/union/union-custom-drop.rs delete mode 100644 src/test/ui/union/union-custom-drop.stderr delete mode 100644 src/test/ui/union/union-manuallydrop-rpass.rs create mode 100644 src/test/ui/union/union-with-drop-fields-lint-rpass.rs rename src/test/ui/union/{union-with-drop-fields.rs => union-with-drop-fields-lint.rs} (60%) create mode 100644 src/test/ui/union/union-with-drop-fields-lint.stderr delete mode 100644 src/test/ui/union/union-with-drop-fields.stderr rename src/test/ui/{reachable => unreachable}/auxiliary/unreachable_variant.rs (100%) rename src/test/ui/{reachable => unreachable}/unreachable-arm.rs (100%) rename src/test/ui/{reachable => unreachable}/unreachable-arm.stderr (100%) rename src/test/ui/{reachable => unreachable}/unreachable-code.rs (100%) rename src/test/ui/{reachable => unreachable}/unreachable-code.stderr (100%) rename src/test/ui/{reachable => unreachable}/unreachable-in-call.rs (100%) rename src/test/ui/{reachable => unreachable}/unreachable-in-call.stderr (100%) rename src/test/ui/{reachable => unreachable}/unreachable-loop-patterns.rs (95%) rename src/test/ui/{reachable => unreachable}/unreachable-loop-patterns.stderr (73%) rename src/test/ui/{reachable => unreachable}/unreachable-try-pattern.rs (94%) rename src/test/ui/{reachable => unreachable}/unreachable-try-pattern.stderr (100%) rename src/test/ui/{reachable => unreachable}/unreachable-variant.rs (100%) rename src/test/ui/{reachable => unreachable}/unreachable-variant.stderr (100%) rename src/test/ui/{reachable => unreachable}/unwarned-match-on-never.rs (100%) rename src/test/ui/{reachable => unreachable}/unwarned-match-on-never.stderr (100%) delete mode 100644 src/test/ui/wf/issue-48638.rs delete mode 100644 src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs delete mode 100644 src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr delete mode 100644 src/test/ui/wf/wf-convert-unsafe-trait-obj.rs delete mode 100644 src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr delete mode 100644 src/test/ui/wf/wf-unsafe-trait-obj-match.rs delete mode 100644 src/test/ui/wf/wf-unsafe-trait-obj-match.stderr delete mode 100644 src/tools/tidy/src/debug_artifacts.rs delete mode 100644 src/tools/tidy/src/error_codes_check.rs diff --git a/.gitignore b/.gitignore index 487867c375d45..81a472451d777 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,6 @@ -# This file should only ignore things that are generated during a `x.py` build, -# generated by common IDEs, and optional files controlled by the user that -# affect the build (such as config.toml). -# In particular, things like `mir_dump` should not be listed here; they are only -# created during manual debugging and many people like to clean up instead of -# having git ignore such leftovers. You can use `.git/info/exclude` to -# configure your local ignore list. +# This file should only ignore things that are generated during a build, +# generated by common IDEs, and optional files controlled by the user +# that affect the build (such as config.toml). # FIXME: This needs cleanup. *~ .#* @@ -56,4 +52,3 @@ config.stamp Session.vim .cargo no_llvm_build -# Before adding new lines, see the comment at the top. diff --git a/.gitmodules b/.gitmodules index 1dcf9ed319f14..3ff5af78097fa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,6 +28,9 @@ [submodule "src/doc/rust-by-example"] path = src/doc/rust-by-example url = https://github.com/rust-lang/rust-by-example.git +[submodule "src/llvm-emscripten"] + path = src/llvm-emscripten + url = https://github.com/rust-lang/llvm.git [submodule "src/stdarch"] path = src/stdarch url = https://github.com/rust-lang/stdarch.git diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index e3708bc485399..ece8dedb0aed7 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,3 +1,40 @@ # The Rust Code of Conduct -The Code of Conduct for this repository [can be found online](https://www.rust-lang.org/conduct.html). +A version of this document [can be found online](https://www.rust-lang.org/conduct.html). + +## Conduct + +**Contact**: [rust-mods@rust-lang.org](mailto:rust-mods@rust-lang.org) + +* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic. +* On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all. +* Please be kind and courteous. There's no need to be mean or rude. +* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer. +* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works. +* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term "harassment" as including the definition in the Citizen Code of Conduct; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups. +* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team][mod_team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back. +* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome. + +## Moderation + + +These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, please contact the [Rust moderation team][mod_team]. + +1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.) +2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed. +3. Moderators will first respond to such remarks with a warning. +4. If the warning is unheeded, the user will be "kicked," i.e., kicked out of the communication channel to cool off. +5. If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded. +6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology. +7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, **in private**. Complaints about bans in-channel are not allowed. +8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others. + +In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely. + +And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could've communicated better — remember that it's your responsibility to make your fellow Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust. + +The enforcement policies listed above apply to all official Rust venues; including official IRC channels (#rust, #rust-internals, #rust-tools, #rust-libs, #rustc, #rust-beginners, #rust-docs, #rust-community, #rust-lang, and #cargo); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion. + +*Adapted from the [Node.js Policy on Trolling](https://blog.izs.me/2012/08/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).* + +[mod_team]: https://www.rust-lang.org/team.html#Moderation-team diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 37a217d2a0452..4daaa986a2dc2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,7 +15,7 @@ links to the major sections: * [Helpful Links and Information](#helpful-links-and-information) If you have questions, please make a post on [internals.rust-lang.org][internals] or -hop on the [Rust Discord server][rust-discord] or [Rust Zulip server][rust-zulip]. +hop on the [Rust Discord server][rust-discord], [Rust Zulip server][rust-zulip] or [#rust-internals][pound-rust-internals]. As a reminder, all contributors are expected to follow our [Code of Conduct][coc]. @@ -25,6 +25,7 @@ to contribute to it in more detail than this document. If this is your first time contributing, the [walkthrough] chapter of the guide can give you a good example of how a typical contribution would go. +[pound-rust-internals]: https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals [internals]: https://internals.rust-lang.org [rust-discord]: http://discord.gg/rust-lang [rust-zulip]: https://rust-lang.zulipchat.com @@ -128,14 +129,6 @@ the master branch to your feature branch. Also, please make sure that fixup commits are squashed into other related commits with meaningful commit messages. -GitHub allows [closing issues using keywords][closing-keywords]. This feature -should be used to keep the issue tracker tidy. However, it is generally preferred -to put the "closes #123" text in the PR description rather than the issue commit; -particularly during rebasing, citing the issue number in the commit can "spam" -the issue in question. - -[closing-keywords]: https://help.github.com/en/articles/closing-issues-using-keywords - Please make sure your pull request is in compliance with Rust's style guidelines by running @@ -411,7 +404,7 @@ If you're looking for somewhere to start, check out the [E-easy][eeasy] tag. There are a number of other ways to contribute to Rust that don't deal with this repository. -Answer questions in the _Get Help!_ channels from the [Rust Discord server][rust-discord], on [users.rust-lang.org][users], +Answer questions in [#rust][pound-rust], or on [users.rust-lang.org][users], or on [StackOverflow][so]. Participate in the [RFC process](https://github.com/rust-lang/rfcs). @@ -420,7 +413,7 @@ Find a [requested community library][community-library], build it, and publish it to [Crates.io](http://crates.io). Easier said than done, but very, very valuable! -[rust-discord]: https://discord.gg/rust-lang +[pound-rust]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust [users]: https://users.rust-lang.org/ [so]: http://stackoverflow.com/questions/tagged/rust [community-library]: https://github.com/rust-lang/rfcs/labels/A-community-library diff --git a/Cargo.lock b/Cargo.lock index fbac2c7879d12..5a92011d57033 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,12 +107,6 @@ dependencies = [ "winapi 0.3.6", ] -[[package]] -name = "autocfg" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" - [[package]] name = "backtrace" version = "0.3.37" @@ -271,7 +265,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.41.0" +version = "0.40.0" dependencies = [ "atty", "bytesize", @@ -373,18 +367,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "cargo_metadata" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d" -dependencies = [ - "semver", - "serde", - "serde_derive", - "serde_json", -] - [[package]] name = "cargotest2" version = "0.1.0" @@ -455,7 +437,7 @@ dependencies = [ name = "clippy" version = "0.0.212" dependencies = [ - "cargo_metadata 0.9.0", + "cargo_metadata", "clippy-mini-macro-test", "clippy_lints", "compiletest_rs", @@ -476,7 +458,7 @@ version = "0.2.0" name = "clippy_lints" version = "0.0.212" dependencies = [ - "cargo_metadata 0.9.0", + "cargo_metadata", "if_chain", "itertools 0.8.0", "lazy_static 1.3.0", @@ -568,9 +550,9 @@ dependencies = [ [[package]] name = "compiletest_rs" -version = "0.3.25" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75b10a18fb53549fdd090846eb01c7f8593914494d1faabc4d3005c436e417a" +checksum = "eb783fe7afb90ec3d3e49ccaf9196d29ab63c6ed61d4b0695839daa580ae3a3d" dependencies = [ "diff", "filetime", @@ -584,6 +566,7 @@ dependencies = [ "serde_derive", "serde_json", "tempfile", + "tester", "winapi 0.3.6", ] @@ -618,7 +601,7 @@ checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" [[package]] name = "crates-io" -version = "0.29.0" +version = "0.28.0" dependencies = [ "curl", "failure", @@ -677,16 +660,6 @@ dependencies = [ "crossbeam-utils 0.6.5", ] -[[package]] -name = "crossbeam-deque" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -dependencies = [ - "crossbeam-epoch 0.7.2", - "crossbeam-utils 0.6.5", -] - [[package]] name = "crossbeam-epoch" version = "0.3.1" @@ -758,24 +731,25 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.24" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08ad3cb89d076a36b0ce5749eec2c9964f70c0c58480ab6b75a91ec4fc206d8" +checksum = "a85f2f95f2bd277d316d1aa8a477687ab4a6942258c7db7c89c187534669979c" dependencies = [ "curl-sys", + "kernel32-sys", "libc", "openssl-probe", "openssl-sys", "schannel", "socket2", - "winapi 0.3.6", + "winapi 0.2.8", ] [[package]] name = "curl-sys" -version = "0.4.22" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9a9a4e417722876332136a00cacf92c2ceb331fab4b52b6a1ad16c6cd79255" +checksum = "9d91a0052d5b982887d8e829bee0faffc7218ea3c6ebd3d6c2c8f678a93c9a42" dependencies = [ "cc", "libc", @@ -1021,7 +995,7 @@ dependencies = [ "proc-macro2 0.4.30", "quote 0.6.12", "syn 0.15.35", - "synstructure 0.10.2", + "synstructure", ] [[package]] @@ -1287,7 +1261,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d" dependencies = [ - "hashbrown 0.5.0", + "hashbrown", "lazy_static 1.3.0", "log", "pest", @@ -1304,19 +1278,10 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" dependencies = [ - "serde", -] - -[[package]] -name = "hashbrown" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd9867f119b19fecb08cd5c326ad4488d7a1da4bf75b4d95d71db742525aaab" -dependencies = [ - "autocfg", "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", + "serde", ] [[package]] @@ -1342,9 +1307,9 @@ checksum = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e" [[package]] name = "home" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3753954f7bd71f0e671afb8b5a992d1724cf43b7f95a563cd4a0bde94659ca8" +checksum = "c07c315e106bd6f83f026a20ddaeef2706782e490db1dcdd37caad38a0e895b3" dependencies = [ "scopeguard 1.0.0", "winapi 0.3.6", @@ -1725,9 +1690,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.64" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dfca3d9957906e8d1e6a0b641dc9a59848e793f1da2165889fd4f62d10d79c" +checksum = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" dependencies = [ "rustc-std-workspace-core", ] @@ -2136,7 +2101,7 @@ name = "miri" version = "0.1.0" dependencies = [ "byteorder", - "cargo_metadata 0.8.0", + "cargo_metadata", "colored", "compiletest_rs", "directories", @@ -2669,9 +2634,9 @@ dependencies = [ [[package]] name = "racer" -version = "2.1.28" +version = "2.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acc70369054bad4ad0c16a3f45cd73e0695361a3af35c7b465e619ac2674f064" +checksum = "dde22b84ab75220015cbd91240222402bf885cbe3a5dc856475771abb82533ae" dependencies = [ "bitflags", "clap", @@ -2828,22 +2793,22 @@ dependencies = [ [[package]] name = "rayon" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" +checksum = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4" dependencies = [ - "crossbeam-deque 0.7.1", + "crossbeam-deque 0.6.3", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.6.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" +checksum = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2" dependencies = [ - "crossbeam-deque 0.7.1", + "crossbeam-deque 0.6.3", "crossbeam-queue", "crossbeam-utils 0.6.5", "lazy_static 1.3.0", @@ -2966,7 +2931,7 @@ name = "rls" version = "1.39.0" dependencies = [ "cargo", - "cargo_metadata 0.8.0", + "cargo_metadata", "clippy_lints", "crossbeam-channel", "difference", @@ -3111,28 +3076,26 @@ dependencies = [ "num_cpus", "parking_lot 0.9.0", "polonius-engine", - "rustc-rayon 0.3.0", - "rustc-rayon-core 0.3.0", + "rustc-rayon", + "rustc-rayon-core", "rustc_apfloat", "rustc_data_structures", "rustc_errors", "rustc_fs_util", - "rustc_index", "rustc_macros", "rustc_target", "scoped-tls", "serialize", "smallvec", "syntax", - "syntax_expand", "syntax_pos", ] [[package]] name = "rustc-ap-arena" -version = "606.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a623fd4805842e9bd0bb6e6dace63efede0ee22de4522a0b03b7c3d15a22f009" +checksum = "f59b76d334bd533f3fdc5c651c27678c5e80fac67c6f7da22ba21a58878c55f5" dependencies = [ "rustc-ap-rustc_data_structures", "smallvec", @@ -3140,15 +3103,15 @@ dependencies = [ [[package]] name = "rustc-ap-graphviz" -version = "606.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee549ade784b444ef10c0240c3487ed785aa65d711071f7984246b15329a17b6" +checksum = "3e632ef08ca17458acfd46d2ead3d541a1c249586cd5329f5fe333dacfab6142" [[package]] name = "rustc-ap-rustc_data_structures" -version = "606.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca545744a5a9b42e3d0410d6290d40de96dd567253fe77f310c1de4afd213dd4" +checksum = "e89e2c7be68185418f3cd56af3df8b29007a59a1cebefa63612d055f9bcb1a36" dependencies = [ "cfg-if", "crossbeam-utils 0.6.5", @@ -3157,22 +3120,21 @@ dependencies = [ "jobserver", "lazy_static 1.3.0", "log", - "parking_lot 0.9.0", + "parking_lot 0.7.1", "rustc-ap-graphviz", - "rustc-ap-rustc_index", "rustc-ap-serialize", "rustc-hash", - "rustc-rayon 0.2.0", - "rustc-rayon-core 0.2.0", + "rustc-rayon", + "rustc-rayon-core", "smallvec", "stable_deref_trait", ] [[package]] name = "rustc-ap-rustc_errors" -version = "606.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6967a41ed38ef4bce0f559fe9a4801d8ba12ac032f40a12a55e72f79d52c9bb" +checksum = "1e47cb380abeb72b01e42b2342d592f7eeea7d536c2f1f0d0e550dc509e46333" dependencies = [ "annotate-snippets", "atty", @@ -3185,57 +3147,46 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "rustc-ap-rustc_index" -version = "606.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "457a5c204ae2fdaa5bdb5b196e58ca59896870d80445fe423063c9453496e3ea" -dependencies = [ - "rustc-ap-serialize", - "smallvec", -] - [[package]] name = "rustc-ap-rustc_lexer" -version = "606.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0c064676f8a08e42a36b0d4e4a102465fb0f4b75e11436cb7f66d2c3fa7139" +checksum = "494cfaf67f49217d67d0774eeecbba61ac89acf478db97ef11f113ed8a959305" dependencies = [ "unicode-xid 0.2.0", ] [[package]] name = "rustc-ap-rustc_macros" -version = "606.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2d77e46159c5288c585decbcdc9d742889c65e307c31e104c7a36d63fe1f5d0" +checksum = "e2e5d36becc59b4497f9cbd3ae0610081de0207a1d0e95c066369167b14f486f" dependencies = [ "itertools 0.8.0", "proc-macro2 0.4.30", "quote 0.6.12", "syn 0.15.35", - "synstructure 0.10.2", + "synstructure", ] [[package]] name = "rustc-ap-rustc_target" -version = "606.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ca895350b0de14d064b499168c93fa183958d5462eb042c927d93623e41ec1" +checksum = "a7bfc5f96dfc3b9f8d5b57884f7f37467ecff6776cd4b8b491a7daece6fdd7c2" dependencies = [ "bitflags", "log", "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_index", "rustc-ap-serialize", "rustc-ap-syntax_pos", ] [[package]] name = "rustc-ap-serialize" -version = "606.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92679240e86f4583cc05f8dcf6439bdab87bac9e6555718469176de9bd52ba20" +checksum = "2bb9ee231cf79eded39c56647499f83d6136ff5c8c0baaa9e21b6febee00f4f6" dependencies = [ "indexmap", "smallvec", @@ -3243,17 +3194,17 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "606.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0c30f8e38c847dbfd9e2f1e472ab06d0bd0a23ab53ae4c5a44912842ce834e" +checksum = "b3827fc208814efbde82d613e31d11b4250ce9e8cf8afe4a4d47bbbd099632c9" dependencies = [ "bitflags", "lazy_static 1.3.0", "log", "rustc-ap-rustc_data_structures", "rustc-ap-rustc_errors", - "rustc-ap-rustc_index", "rustc-ap-rustc_lexer", + "rustc-ap-rustc_macros", "rustc-ap-rustc_target", "rustc-ap-serialize", "rustc-ap-syntax_pos", @@ -3263,14 +3214,13 @@ dependencies = [ [[package]] name = "rustc-ap-syntax_pos" -version = "606.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdaa0fb40143b4b878256ac4e2b498885daafc269502504d91929eab4744bf4" +checksum = "930ed81c34f325e512cc315c04d676fa84a373879d5c43bb54054a0522b05213" dependencies = [ "cfg-if", "rustc-ap-arena", "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_index", "rustc-ap-rustc_macros", "rustc-ap-serialize", "scoped-tls", @@ -3314,18 +3264,7 @@ checksum = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" dependencies = [ "crossbeam-deque 0.2.0", "either", - "rustc-rayon-core 0.2.0", -] - -[[package]] -name = "rustc-rayon" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" -dependencies = [ - "crossbeam-deque 0.7.1", - "either", - "rustc-rayon-core 0.3.0", + "rustc-rayon-core", ] [[package]] @@ -3340,19 +3279,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "rustc-rayon-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2427831f0053ea3ea73559c8eabd893133a51b251d142bacee53c62a288cb3" -dependencies = [ - "crossbeam-deque 0.7.1", - "crossbeam-queue", - "crossbeam-utils 0.6.5", - "lazy_static 1.3.0", - "num_cpus", -] - [[package]] name = "rustc-serialize" version = "0.3.24" @@ -3436,11 +3362,9 @@ dependencies = [ "rustc_errors", "rustc_fs_util", "rustc_incremental", - "rustc_index", "rustc_target", "serialize", "syntax", - "syntax_expand", "syntax_pos", "tempfile", ] @@ -3474,9 +3398,8 @@ dependencies = [ "log", "parking_lot 0.9.0", "rustc-hash", - "rustc-rayon 0.3.0", - "rustc-rayon-core 0.3.0", - "rustc_index", + "rustc-rayon", + "rustc-rayon-core", "serialize", "smallvec", "stable_deref_trait", @@ -3495,7 +3418,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_interface", - "rustc_lint", "rustc_metadata", "rustc_mir", "rustc_plugin", @@ -3541,14 +3463,6 @@ dependencies = [ "syntax_pos", ] -[[package]] -name = "rustc_index" -version = "0.0.0" -dependencies = [ - "serialize", - "smallvec", -] - [[package]] name = "rustc_interface" version = "0.0.0" @@ -3556,7 +3470,7 @@ dependencies = [ "log", "once_cell", "rustc", - "rustc-rayon 0.3.0", + "rustc-rayon", "rustc_codegen_ssa", "rustc_codegen_utils", "rustc_data_structures", @@ -3569,13 +3483,11 @@ dependencies = [ "rustc_plugin_impl", "rustc_privacy", "rustc_resolve", - "rustc_target", "rustc_traits", "rustc_typeck", "serialize", "smallvec", "syntax", - "syntax_expand", "syntax_ext", "syntax_pos", "tempfile", @@ -3595,7 +3507,6 @@ dependencies = [ "log", "rustc", "rustc_data_structures", - "rustc_index", "rustc_target", "syntax", "syntax_pos", @@ -3625,10 +3536,10 @@ name = "rustc_macros" version = "0.1.0" dependencies = [ "itertools 0.8.0", - "proc-macro2 1.0.3", - "quote 1.0.2", - "syn 1.0.5", - "synstructure 0.12.1", + "proc-macro2 0.4.30", + "quote 0.6.12", + "syn 0.15.35", + "synstructure", ] [[package]] @@ -3641,13 +3552,11 @@ dependencies = [ "rustc", "rustc_data_structures", "rustc_errors", - "rustc_index", "rustc_target", "serialize", "smallvec", "stable_deref_trait", "syntax", - "syntax_expand", "syntax_pos", ] @@ -3665,7 +3574,6 @@ dependencies = [ "rustc_apfloat", "rustc_data_structures", "rustc_errors", - "rustc_index", "rustc_lexer", "rustc_target", "serialize", @@ -3693,10 +3601,7 @@ dependencies = [ "rustc", "rustc_data_structures", "rustc_errors", - "rustc_index", - "rustc_target", "syntax", - "syntax_expand", "syntax_pos", ] @@ -3714,7 +3619,6 @@ dependencies = [ "rustc", "rustc_metadata", "syntax", - "syntax_expand", "syntax_pos", ] @@ -3743,7 +3647,6 @@ dependencies = [ "rustc_metadata", "smallvec", "syntax", - "syntax_expand", "syntax_pos", ] @@ -3770,7 +3673,6 @@ dependencies = [ "bitflags", "log", "rustc_data_structures", - "rustc_index", "serialize", "syntax_pos", ] @@ -3819,7 +3721,6 @@ dependencies = [ "rustc", "rustc_data_structures", "rustc_errors", - "rustc_index", "rustc_target", "smallvec", "syntax", @@ -3841,7 +3742,7 @@ version = "0.0.0" dependencies = [ "minifier", "pulldown-cmark 0.5.3", - "rustc-rayon 0.3.0", + "rustc-rayon", "tempfile", ] @@ -3880,11 +3781,11 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.9" +version = "1.4.8" dependencies = [ "annotate-snippets", "bytecount", - "cargo_metadata 0.8.0", + "cargo_metadata", "derive-new", "diff", "dirs", @@ -4158,7 +4059,7 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown 0.6.2", + "hashbrown", "libc", "panic_abort", "panic_unwind", @@ -4327,18 +4228,6 @@ dependencies = [ "unicode-xid 0.1.0", ] -[[package]] -name = "synstructure" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" -dependencies = [ - "proc-macro2 1.0.3", - "quote 1.0.2", - "syn 1.0.5", - "unicode-xid 0.2.0", -] - [[package]] name = "syntax" version = "0.0.0" @@ -4348,31 +4237,11 @@ dependencies = [ "log", "rustc_data_structures", "rustc_errors", - "rustc_index", - "rustc_lexer", - "rustc_target", - "scoped-tls", - "serialize", - "smallvec", - "syntax_pos", -] - -[[package]] -name = "syntax_expand" -version = "0.0.0" -dependencies = [ - "bitflags", - "lazy_static 1.3.0", - "log", - "rustc_data_structures", - "rustc_errors", - "rustc_index", "rustc_lexer", "rustc_target", "scoped-tls", "serialize", "smallvec", - "syntax", "syntax_pos", ] @@ -4387,7 +4256,6 @@ dependencies = [ "rustc_target", "smallvec", "syntax", - "syntax_expand", "syntax_pos", ] @@ -4398,7 +4266,6 @@ dependencies = [ "arena", "cfg-if", "rustc_data_structures", - "rustc_index", "rustc_macros", "scoped-tls", "serialize", @@ -4456,6 +4323,16 @@ dependencies = [ "std", ] +[[package]] +name = "term" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" +dependencies = [ + "kernel32-sys", + "winapi 0.2.8", +] + [[package]] name = "term" version = "0.6.0" @@ -4512,6 +4389,17 @@ dependencies = [ "term 0.0.0", ] +[[package]] +name = "tester" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e812cb26c597f86a49b26dbb58b878bd2a2b4b93fc069dc39499228fe556ff6" +dependencies = [ + "getopts", + "libc", + "term 0.4.6", +] + [[package]] name = "textwrap" version = "0.11.0" diff --git a/README.md b/README.md index c5468a2924888..96d7e938be2f2 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,6 @@ or reading the [rustc guide][rustcguidebuild]. * `curl` * `git` * `ssl` which comes in `libssl-dev` or `openssl-devel` - * `pkg-config` if you are compiling on Linux and targeting Linux 2. Clone the [source] with `git`: @@ -244,17 +243,19 @@ The Rust community congregates in a few places: To contribute to Rust, please see [CONTRIBUTING](CONTRIBUTING.md). -Most real-time collaboration happens in a variety of channels on the -[Rust Discord server][rust-discord], with channels dedicated for getting help, -community, documentation, and all major contribution areas in the Rust ecosystem. -A good place to ask for help would be the #help channel. +Rust has an [IRC] culture and most real-time collaboration happens in a +variety of channels on Mozilla's IRC network, irc.mozilla.org. The +most popular channel is [#rust], a venue for general discussion about +Rust. And a good place to ask for help would be [#rust-beginners]. The [rustc guide] might be a good place to start if you want to find out how various parts of the compiler work. Also, you may find the [rustdocs for the compiler itself][rustdocs] useful. -[rust-discord]: https://discord.gg/rust-lang +[IRC]: https://en.wikipedia.org/wiki/Internet_Relay_Chat +[#rust]: irc://irc.mozilla.org/rust +[#rust-beginners]: irc://irc.mozilla.org/rust-beginners [rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html [rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ diff --git a/config.toml.example b/config.toml.example index e832570ed982e..848147c2974c1 100644 --- a/config.toml.example +++ b/config.toml.example @@ -258,9 +258,10 @@ [rust] # Whether or not to optimize the compiler and standard library. -# WARNING: Building with optimize = false is NOT SUPPORTED. Due to bootstrapping, -# building without optimizations takes much longer than optimizing. Further, some platforms -# fail to build without this optimization (c.f. #65352). +# +# Note: the slowness of the non optimized compiler compiling itself usually +# outweighs the time gains in not doing optimizations, therefore a +# full bootstrap takes much more time with `optimize` set to false. #optimize = true # Indicates that the build should be configured for debugging Rust. A @@ -340,9 +341,6 @@ # nightly features #channel = "dev" -# The root location of the MUSL installation directory. -#musl-root = "..." - # By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix # platforms to ensure that the compiler is usable by default from the build # directory (as it links to a number of dynamic libraries). This may not be @@ -376,7 +374,9 @@ # This is an array of the codegen backends that will be compiled for the rustc # that's being compiled. The default is to only build the LLVM codegen backend, -# and currently the only standard option supported is `"llvm"` +# but you can also optionally enable the "emscripten" backend for asm.js or +# make this an empty array (but that probably won't get too far in the +# bootstrap) #codegen-backends = ["llvm"] # This is the name of the directory in which codegen backends will get installed diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index c501378bff549..3e877fc4e317c 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -328,8 +328,6 @@ are: `Config` struct. * Adding a sanity check? Take a look at `bootstrap/sanity.rs`. -If you have any questions feel free to reach out on `#infra` channel in the -[Rust Discord server][rust-discord] or ask on internals.rust-lang.org. When -you encounter bugs, please file issues on the rust-lang/rust issue tracker. - -[rust-discord]: https://discord.gg/rust-lang +If you have any questions feel free to reach out on `#rust-infra` on IRC or ask on +internals.rust-lang.org. When you encounter bugs, please file issues on the +rust-lang/rust issue tracker. diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 4caf36a6f2a51..65129eeeec504 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -734,6 +734,10 @@ def update_submodules(self): if module.endswith("llvm-project"): if self.get_toml('llvm-config') and self.get_toml('lld') != 'true': continue + if module.endswith("llvm-emscripten"): + backends = self.get_toml('codegen-backends') + if backends is None or not 'emscripten' in backends: + continue check = self.check_submodule(module, slow_submodules) filtered_submodules.append((module, check)) submodules_names.append(module) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 2748903f2d475..5d586f0c461db 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -443,7 +443,6 @@ impl<'a> Builder<'a> { dist::Rustc, dist::DebuggerScripts, dist::Std, - dist::RustcDev, dist::Analysis, dist::Src, dist::PlainSourceTarball, @@ -818,22 +817,12 @@ impl<'a> Builder<'a> { let mut rustflags = Rustflags::new(&target); if stage != 0 { - if let Ok(s) = env::var("CARGOFLAGS_NOT_BOOTSTRAP") { - cargo.args(s.split_whitespace()); - } rustflags.env("RUSTFLAGS_NOT_BOOTSTRAP"); } else { - if let Ok(s) = env::var("CARGOFLAGS_BOOTSTRAP") { - cargo.args(s.split_whitespace()); - } rustflags.env("RUSTFLAGS_BOOTSTRAP"); rustflags.arg("--cfg=bootstrap"); } - if let Ok(s) = env::var("CARGOFLAGS") { - cargo.args(s.split_whitespace()); - } - match mode { Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {}, Mode::Rustc | Mode::Codegen | Mode::ToolRustc => { @@ -981,7 +970,6 @@ impl<'a> Builder<'a> { Some("-Wl,-rpath,@loader_path/../lib") } else if !target.contains("windows") && !target.contains("wasm32") && - !target.contains("emscripten") && !target.contains("fuchsia") { Some("-Wl,-rpath,$ORIGIN/../lib") } else { diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index 4310f2c6fa140..53071df855297 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -161,7 +161,7 @@ impl Ord for Interned { } } -struct TyIntern { +struct TyIntern { items: Vec, set: HashMap>, } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index df1c72575846b..cadb9a7e441f2 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -55,7 +55,6 @@ impl Step for Std { cargo, args(builder.kind), &libstd_stamp(builder, compiler, target), - vec![], true); let libdir = builder.sysroot_libdir(compiler, target); @@ -104,7 +103,6 @@ impl Step for Rustc { cargo, args(builder.kind), &librustc_stamp(builder, compiler, target), - vec![], true); let libdir = builder.sysroot_libdir(compiler, target); @@ -157,7 +155,6 @@ impl Step for CodegenBackend { cargo, args(builder.kind), &codegen_backend_stamp(builder, compiler, target, backend), - vec![], true); } } @@ -202,7 +199,6 @@ impl Step for Rustdoc { cargo, args(builder.kind), &rustdoc_stamp(builder, compiler, target), - vec![], true); let libdir = builder.sysroot_libdir(compiler, target); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index da8d43ed49b7f..6ea32edfb208b 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -69,7 +69,7 @@ impl Step for Std { return; } - let mut target_deps = builder.ensure(StartupObjects { compiler, target }); + builder.ensure(StartupObjects { compiler, target }); let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); if compiler_to_use != compiler { @@ -91,7 +91,7 @@ impl Step for Std { return; } - target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter()); + copy_third_party_objects(builder, &compiler, target); let mut cargo = builder.cargo(compiler, Mode::Std, target, "build"); std_cargo(builder, &compiler, target, &mut cargo); @@ -102,7 +102,6 @@ impl Step for Std { cargo, vec![], &libstd_stamp(builder, compiler, target), - target_deps, false); builder.ensure(StdLink { @@ -114,22 +113,9 @@ impl Step for Std { } /// Copies third pary objects needed by various targets. -fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: Interned) - -> Vec -{ +fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: Interned) { let libdir = builder.sysroot_libdir(*compiler, target); - let mut target_deps = vec![]; - - let mut copy_and_stamp = |sourcedir: &Path, name: &str| { - let target = libdir.join(name); - builder.copy( - &sourcedir.join(name), - &target, - ); - target_deps.push(target); - }; - // Copies the crt(1,i,n).o startup objects // // Since musl supports fully static linking, we can cross link for it even @@ -137,13 +123,19 @@ fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: // files. As those shipped with glibc won't work, copy the ones provided by // musl so we have them on linux-gnu hosts. if target.contains("musl") { - let srcdir = builder.musl_root(target).unwrap().join("lib"); for &obj in &["crt1.o", "crti.o", "crtn.o"] { - copy_and_stamp(&srcdir, obj); + builder.copy( + &builder.musl_root(target).unwrap().join("lib").join(obj), + &libdir.join(obj), + ); } } else if target.ends_with("-wasi") { - let srcdir = builder.wasi_root(target).unwrap().join("lib/wasm32-wasi"); - copy_and_stamp(&srcdir, "crt1.o"); + for &obj in &["crt1.o"] { + builder.copy( + &builder.wasi_root(target).unwrap().join("lib/wasm32-wasi").join(obj), + &libdir.join(obj), + ); + } } // Copies libunwind.a compiled to be linked wit x86_64-fortanix-unknown-sgx. @@ -153,11 +145,11 @@ fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: // which is provided by std for this target. if target == "x86_64-fortanix-unknown-sgx" { let src_path_env = "X86_FORTANIX_SGX_LIBS"; + let obj = "libunwind.a"; let src = env::var(src_path_env).expect(&format!("{} not found in env", src_path_env)); - copy_and_stamp(Path::new(&src), "libunwind.a"); + let src = Path::new(&src).join(obj); + builder.copy(&src, &libdir.join(obj)); } - - target_deps } /// Configure cargo to compile the standard library, adding appropriate env vars @@ -218,6 +210,7 @@ pub fn std_cargo(builder: &Builder<'_>, // config.toml equivalent) is used let llvm_config = builder.ensure(native::Llvm { target: builder.config.build, + emscripten: false, }); cargo.env("LLVM_CONFIG", llvm_config); cargo.env("RUSTC_BUILD_SANITIZERS", "1"); @@ -314,7 +307,7 @@ pub struct StartupObjects { } impl Step for StartupObjects { - type Output = Vec; + type Output = (); fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/rtstartup") @@ -333,15 +326,13 @@ impl Step for StartupObjects { /// They don't require any library support as they're just plain old object /// files, so we just use the nightly snapshot compiler to always build them (as /// no other compilers are guaranteed to be available). - fn run(self, builder: &Builder<'_>) -> Vec { + fn run(self, builder: &Builder<'_>) { let for_compiler = self.compiler; let target = self.target; if !target.contains("windows-gnu") { - return vec![] + return } - let mut target_deps = vec![]; - let src_dir = &builder.src.join("src/rtstartup"); let dst_dir = &builder.native_dir(target).join("rtstartup"); let sysroot_dir = &builder.sysroot_libdir(for_compiler, target); @@ -360,9 +351,7 @@ impl Step for StartupObjects { .arg(src_file)); } - let target = sysroot_dir.join(file.to_string() + ".o"); - builder.copy(dst_file, &target); - target_deps.push(target); + builder.copy(dst_file, &sysroot_dir.join(file.to_string() + ".o")); } for obj in ["crt2.o", "dllcrt2.o"].iter() { @@ -370,12 +359,8 @@ impl Step for StartupObjects { builder.cc(target), target, obj); - let target = sysroot_dir.join(obj); - builder.copy(&src, &target); - target_deps.push(target); + builder.copy(&src, &sysroot_dir.join(obj)); } - - target_deps } } @@ -453,7 +438,6 @@ impl Step for Rustc { cargo, vec![], &librustc_stamp(builder, compiler, target), - vec![], false); builder.ensure(RustcLink { @@ -602,7 +586,7 @@ impl Step for CodegenBackend { let tmp_stamp = out_dir.join(".tmp.stamp"); - let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false); + let files = run_cargo(builder, cargo, vec![], &tmp_stamp, false); if builder.config.dry_run { return; } @@ -631,27 +615,36 @@ pub fn build_codegen_backend(builder: &Builder<'_>, compiler: &Compiler, target: Interned, backend: Interned) -> String { + let mut features = String::new(); + match &*backend { - "llvm" => { + "llvm" | "emscripten" => { // Build LLVM for our target. This will implicitly build the // host LLVM if necessary. let llvm_config = builder.ensure(native::Llvm { target, + emscripten: backend == "emscripten", }); + if backend == "emscripten" { + features.push_str(" emscripten"); + } + builder.info(&format!("Building stage{} codegen artifacts ({} -> {}, {})", compiler.stage, &compiler.host, target, backend)); // Pass down configuration from the LLVM build into the build of // librustc_llvm and librustc_codegen_llvm. - if builder.is_rust_llvm(target) { + if builder.is_rust_llvm(target) && backend != "emscripten" { cargo.env("LLVM_RUSTLLVM", "1"); } cargo.env("LLVM_CONFIG", &llvm_config); - let target_config = builder.config.target_config.get(&target); - if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { - cargo.env("CFG_LLVM_ROOT", s); + if backend != "emscripten" { + let target_config = builder.config.target_config.get(&target); + if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { + cargo.env("CFG_LLVM_ROOT", s); + } } // Some LLVM linker flags (-L and -l) may be needed to link librustc_llvm. if let Some(ref s) = builder.config.llvm_ldflags { @@ -669,7 +662,9 @@ pub fn build_codegen_backend(builder: &Builder<'_>, "libstdc++.a"); cargo.env("LLVM_STATIC_STDCPP", file); } - if builder.config.llvm_link_shared || builder.config.llvm_thin_lto { + if builder.config.llvm_link_shared || + (builder.config.llvm_thin_lto && backend != "emscripten") + { cargo.env("LLVM_LINK_SHARED", "1"); } if builder.config.llvm_use_libcxx { @@ -681,7 +676,8 @@ pub fn build_codegen_backend(builder: &Builder<'_>, } _ => panic!("unknown backend: {}", backend), } - String::new() + + features } /// Creates the `codegen-backends` folder for a compiler that's about to be @@ -958,7 +954,6 @@ pub fn run_cargo(builder: &Builder<'_>, cargo: Cargo, tail_args: Vec, stamp: &Path, - additional_target_deps: Vec, is_check: bool) -> Vec { @@ -1075,7 +1070,6 @@ pub fn run_cargo(builder: &Builder<'_>, deps.push((path_to_add.into(), false)); } - deps.extend(additional_target_deps.into_iter().map(|d| (d, false))); deps.sort(); let mut new_contents = Vec::new(); for (dep, proc_macro) in deps.iter() { diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index d1bdfa0a76763..52b5cd888df9c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -200,15 +200,16 @@ struct Build { target: Vec, cargo: Option, rustc: Option, - docs: Option, + low_priority: Option, compiler_docs: Option, + docs: Option, submodules: Option, fast_submodules: Option, gdb: Option, - nodejs: Option, - python: Option, locked_deps: Option, vendor: Option, + nodejs: Option, + python: Option, full_bootstrap: Option, extended: Option, tools: Option>, @@ -216,7 +217,6 @@ struct Build { sanitizers: Option, profiler: Option, cargo_native_static: Option, - low_priority: Option, configure_args: Option>, local_rebuild: Option, print_step_timings: Option, @@ -228,11 +228,11 @@ struct Build { struct Install { prefix: Option, sysconfdir: Option, + datadir: Option, docdir: Option, bindir: Option, libdir: Option, mandir: Option, - datadir: Option, // standard paths, currently unused infodir: Option, @@ -243,14 +243,14 @@ struct Install { #[derive(Deserialize, Default)] #[serde(deny_unknown_fields, rename_all = "kebab-case")] struct Llvm { + ccache: Option, + ninja: Option, + assertions: Option, optimize: Option, thin_lto: Option, release_debuginfo: Option, - assertions: Option, - ccache: Option, version_check: Option, static_libstdcpp: Option, - ninja: Option, targets: Option, experimental_targets: Option, link_jobs: Option, @@ -293,7 +293,6 @@ impl Default for StringOrBool { #[serde(deny_unknown_fields, rename_all = "kebab-case")] struct Rust { optimize: Option, - debug: Option, codegen_units: Option, codegen_units_std: Option, debug_assertions: Option, @@ -302,24 +301,25 @@ struct Rust { debuginfo_level_std: Option, debuginfo_level_tools: Option, debuginfo_level_tests: Option, - backtrace: Option, - incremental: Option, parallel_compiler: Option, + backtrace: Option, default_linker: Option, channel: Option, musl_root: Option, rpath: Option, - verbose_tests: Option, optimize_tests: Option, codegen_tests: Option, ignore_git: Option, + debug: Option, dist_src: Option, + verbose_tests: Option, + incremental: Option, save_toolstates: Option, codegen_backends: Option>, codegen_backends_dir: Option, lld: Option, - llvm_tools: Option, lldb: Option, + llvm_tools: Option, deny_warnings: Option, backtrace_on_ice: Option, verify_llvm_ir: Option, @@ -333,13 +333,13 @@ struct Rust { #[derive(Deserialize, Default)] #[serde(deny_unknown_fields, rename_all = "kebab-case")] struct TomlTarget { + llvm_config: Option, + llvm_filecheck: Option, cc: Option, cxx: Option, ar: Option, ranlib: Option, linker: Option, - llvm_config: Option, - llvm_filecheck: Option, android_ndk: Option, crt_static: Option, musl_root: Option, @@ -668,6 +668,7 @@ impl Config { pub fn llvm_enabled(&self) -> bool { self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) + || self.rust_codegen_backends.contains(&INTERNER.intern_str("emscripten")) } } diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 76509134f7ccd..346f0cb2039c0 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -55,6 +55,7 @@ def v(*args): o("dist-src", "rust.dist-src", "when building tarballs enables building a source tarball") o("cargo-native-static", "build.cargo-native-static", "static native libraries in cargo") o("profiler", "build.profiler", "build the profiler runtime") +o("emscripten", None, "compile the emscripten backend as well as LLVM") o("full-tools", None, "enable all tools") o("lld", "rust.lld", "build lld") o("lldb", "rust.lldb", "build lldb") @@ -334,8 +335,10 @@ def set(key, value): set('build.host', value.split(',')) elif option.name == 'target': set('build.target', value.split(',')) + elif option.name == 'emscripten': + set('rust.codegen-backends', ['llvm', 'emscripten']) elif option.name == 'full-tools': - set('rust.codegen-backends', ['llvm']) + set('rust.codegen-backends', ['llvm', 'emscripten']) set('rust.lld', True) set('rust.llvm-tools', True) set('build.extended', True) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 93143570b0fe1..d9dff77a30e6b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -637,28 +637,6 @@ impl Step for DebuggerScripts { } } -fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool { - // 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. - if compiler.host != builder.config.build { - builder.info("\tskipping, not a build host"); - true - } else { - false - } -} - -/// Copy stamped files into an image's `target/lib` directory. -fn copy_target_libs(builder: &Builder<'_>, target: &str, image: &Path, stamp: &Path) { - let dst = image.join("lib/rustlib").join(target).join("lib"); - t!(fs::create_dir_all(&dst)); - for (path, host) in builder.read_stamp_file(stamp) { - if !host || builder.config.build == target { - builder.copy(&path, &dst.join(path.file_name().unwrap())); - } - } -} - #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub compiler: Compiler, @@ -689,19 +667,44 @@ impl Step for Std { let target = self.target; let name = pkgname(builder, "rust-std"); - let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target)); - if skip_host_target_lib(builder, compiler) { - return archive; + + // 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. + if compiler.host != builder.config.build { + builder.info("\tskipping, not a build host"); + return distdir(builder).join(format!("{}-{}.tar.gz", name, target)); } - builder.ensure(compile::Std { compiler, target }); + // We want to package up as many target libraries as possible + // for the `rust-std` package, so if this is a host target we + // depend on librustc and otherwise we just depend on libtest. + if builder.hosts.iter().any(|t| t == target) { + builder.ensure(compile::Rustc { compiler, target }); + } else { + builder.ensure(compile::Std { compiler, target }); + } let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); - let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); - let stamp = compile::libstd_stamp(builder, compiler_to_use, target); - copy_target_libs(builder, &target, &image, &stamp); + let dst = image.join("lib/rustlib").join(target); + t!(fs::create_dir_all(&dst)); + let mut src = builder.sysroot_libdir(compiler, target).to_path_buf(); + src.pop(); // Remove the trailing /lib folder from the sysroot_libdir + builder.cp_filtered(&src, &dst, &|path| { + if let Some(name) = path.file_name().and_then(|s| s.to_str()) { + if name == builder.config.rust_codegen_backends_dir.as_str() { + return false + } + if name == "bin" { + return false + } + if name.contains("LLVM") { + return false + } + } + true + }); let mut cmd = rust_installer(builder); cmd.arg("generate") @@ -720,73 +723,7 @@ impl Step for Std { let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); - archive - } -} - -#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] -pub struct RustcDev { - pub compiler: Compiler, - pub target: Interned, -} - -impl Step for RustcDev { - type Output = PathBuf; - const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("rustc-dev") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(RustcDev { - compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.build, - run.target, - ), - target: run.target, - }); - } - - fn run(self, builder: &Builder<'_>) -> PathBuf { - let compiler = self.compiler; - let target = self.target; - - let name = pkgname(builder, "rustc-dev"); - let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target)); - if skip_host_target_lib(builder, compiler) { - return archive; - } - - builder.ensure(compile::Rustc { compiler, target }); - - let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); - let _ = fs::remove_dir_all(&image); - - let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); - let stamp = compile::librustc_stamp(builder, compiler_to_use, target); - copy_target_libs(builder, &target, &image, &stamp); - - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-is-ready-to-develop.") - .arg("--image-dir").arg(&image) - .arg("--work-dir").arg(&tmpdir(builder)) - .arg("--output-dir").arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, target)) - .arg(format!("--component-name=rustc-dev-{}", target)) - .arg("--legacy-manifest-dirs=rustlib,cargo"); - - builder.info(&format!("Dist rustc-dev stage{} ({} -> {})", - compiler.stage, &compiler.host, target)); - let _time = timeit(builder); - builder.run(&mut cmd); - builder.remove_dir(&image); - archive + distdir(builder).join(format!("{}-{}.tar.gz", name, target)) } } @@ -889,6 +826,7 @@ fn copy_src_dirs(builder: &Builder<'_>, src_dirs: &[&str], exclude_dirs: &[&str] const LLVM_TEST: &[&str] = &[ "llvm-project/llvm/test", "llvm-project\\llvm\\test", + "llvm-emscripten/test", "llvm-emscripten\\test", ]; if LLVM_TEST.iter().any(|path| spath.contains(path)) && (spath.ends_with(".ll") || @@ -896,6 +834,9 @@ fn copy_src_dirs(builder: &Builder<'_>, src_dirs: &[&str], exclude_dirs: &[&str] spath.ends_with(".s")) { return false } + if spath.contains("test/emscripten") || spath.contains("test\\emscripten") { + return false + } let full_path = Path::new(dir).join(path); if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index d1cf1cbca7844..9203a558f6465 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -232,6 +232,7 @@ pub struct Build { miri_info: channel::GitInfo, rustfmt_info: channel::GitInfo, in_tree_llvm_info: channel::GitInfo, + emscripten_llvm_info: channel::GitInfo, local_rebuild: bool, fail_fast: bool, doc_tests: DocTests, @@ -350,6 +351,7 @@ impl Build { // we always try to use git for LLVM builds let in_tree_llvm_info = channel::GitInfo::new(false, &src.join("src/llvm-project")); + let emscripten_llvm_info = channel::GitInfo::new(false, &src.join("src/llvm-emscripten")); let mut build = Build { initial_rustc: config.initial_rustc.clone(), @@ -374,6 +376,7 @@ impl Build { miri_info, rustfmt_info, in_tree_llvm_info, + emscripten_llvm_info, cc: HashMap::new(), cxx: HashMap::new(), ar: HashMap::new(), @@ -550,6 +553,10 @@ impl Build { self.out.join(&*target).join("llvm") } + fn emscripten_llvm_out(&self, target: Interned) -> PathBuf { + self.out.join(&*target).join("llvm-emscripten") + } + fn lld_out(&self, target: Interned) -> PathBuf { self.out.join(&*target).join("lld") } @@ -1119,7 +1126,7 @@ impl Build { } let mut paths = Vec::new(); - let contents = t!(fs::read(stamp), &stamp); + let contents = t!(fs::read(stamp)); // This is the method we use for extracting paths from the stamp file passed to us. See // run_cargo for more information (in compile.rs). for part in contents.split(|b| *b == 0) { @@ -1137,7 +1144,6 @@ impl Build { pub fn copy(&self, src: &Path, dst: &Path) { if self.config.dry_run { return; } self.verbose_than(1, &format!("Copy {:?} to {:?}", src, dst)); - if src == dst { return; } let _ = fs::remove_file(&dst); let metadata = t!(src.symlink_metadata()); if metadata.file_type().is_symlink() { diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 97cdd25680162..7bf9ea2688f4c 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -28,6 +28,7 @@ use crate::GitRepo; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Llvm { pub target: Interned, + pub emscripten: bool, } impl Step for Llvm { @@ -39,35 +40,46 @@ impl Step for Llvm { run.path("src/llvm-project") .path("src/llvm-project/llvm") .path("src/llvm") + .path("src/llvm-emscripten") } fn make_run(run: RunConfig<'_>) { + let emscripten = run.path.ends_with("llvm-emscripten"); run.builder.ensure(Llvm { target: run.target, + emscripten, }); } /// Compile LLVM for `target`. fn run(self, builder: &Builder<'_>) -> PathBuf { let target = self.target; + let emscripten = self.emscripten; // If we're using a custom LLVM bail out here, but we can only use a // custom LLVM for the build triple. - if let Some(config) = builder.config.target_config.get(&target) { - if let Some(ref s) = config.llvm_config { - check_llvm_version(builder, s); - return s.to_path_buf() + if !self.emscripten { + if let Some(config) = builder.config.target_config.get(&target) { + if let Some(ref s) = config.llvm_config { + check_llvm_version(builder, s); + return s.to_path_buf() + } } } - let llvm_info = &builder.in_tree_llvm_info; - let root = "src/llvm-project/llvm"; - let out_dir = builder.llvm_out(target); - let mut llvm_config_ret_dir = builder.llvm_out(builder.config.build); - if !builder.config.build.contains("msvc") || builder.config.ninja { - llvm_config_ret_dir.push("build"); - } - llvm_config_ret_dir.push("bin"); + let (llvm_info, root, out_dir, llvm_config_ret_dir) = if emscripten { + let info = &builder.emscripten_llvm_info; + let dir = builder.emscripten_llvm_out(target); + let config_dir = dir.join("bin"); + (info, "src/llvm-emscripten", dir, config_dir) + } else { + let info = &builder.in_tree_llvm_info; + let mut dir = builder.llvm_out(builder.config.build); + if !builder.config.build.contains("msvc") || builder.config.ninja { + dir.push("build"); + } + (info, "src/llvm-project/llvm", builder.llvm_out(target), dir.join("bin")) + }; let build_llvm_config = llvm_config_ret_dir .join(exe("llvm-config", &*builder.config.build)); @@ -95,7 +107,8 @@ impl Step for Llvm { } } - builder.info(&format!("Building LLVM for {}", target)); + let descriptor = if emscripten { "Emscripten " } else { "" }; + builder.info(&format!("Building {}LLVM for {}", descriptor, target)); let _time = util::timeit(&builder); t!(fs::create_dir_all(&out_dir)); @@ -110,15 +123,23 @@ impl Step for Llvm { // NOTE: remember to also update `config.toml.example` when changing the // defaults! - let llvm_targets = match &builder.config.llvm_targets { - Some(s) => s, - None => "AArch64;ARM;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;\ - Sparc;SystemZ;WebAssembly;X86", + let llvm_targets = if self.emscripten { + "JSBackend" + } else { + match builder.config.llvm_targets { + Some(ref s) => s, + None => "AArch64;ARM;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;\ + Sparc;SystemZ;WebAssembly;X86", + } }; - let llvm_exp_targets = match builder.config.llvm_experimental_targets { - Some(ref s) => s, - None => "", + let llvm_exp_targets = if self.emscripten { + "" + } else { + match builder.config.llvm_experimental_targets { + Some(ref s) => s, + None => "", + } }; let assertions = if builder.config.llvm_assertions {"ON"} else {"OFF"}; @@ -136,29 +157,39 @@ impl Step for Llvm { .define("WITH_POLLY", "OFF") .define("LLVM_ENABLE_TERMINFO", "OFF") .define("LLVM_ENABLE_LIBEDIT", "OFF") - .define("LLVM_ENABLE_BINDINGS", "OFF") .define("LLVM_ENABLE_Z3_SOLVER", "OFF") .define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string()) .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) .define("LLVM_DEFAULT_TARGET_TRIPLE", target); - if builder.config.llvm_thin_lto { + if builder.config.llvm_thin_lto && !emscripten { cfg.define("LLVM_ENABLE_LTO", "Thin"); if !target.contains("apple") { cfg.define("LLVM_ENABLE_LLD", "ON"); } } + // By default, LLVM will automatically find OCaml and, if it finds it, + // install the LLVM bindings in LLVM_OCAML_INSTALL_PATH, which defaults + // to /usr/bin/ocaml. + // This causes problem for non-root builds of Rust. Side-step the issue + // by setting LLVM_OCAML_INSTALL_PATH to a relative path, so it installs + // in the prefix. + cfg.define("LLVM_OCAML_INSTALL_PATH", + env::var_os("LLVM_OCAML_INSTALL_PATH").unwrap_or_else(|| "usr/lib/ocaml".into())); + + let want_lldb = builder.config.lldb_enabled && !self.emscripten; + // This setting makes the LLVM tools link to the dynamic LLVM library, // which saves both memory during parallel links and overall disk space // for the tools. We don't do this on every platform as it doesn't work // equally well everywhere. - if builder.llvm_link_tools_dynamically(target) { + if builder.llvm_link_tools_dynamically(target) && !emscripten { cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); } // For distribution we want the LLVM tools to be *statically* linked to libstdc++ - if builder.config.llvm_tools_enabled || builder.config.lldb_enabled { + if builder.config.llvm_tools_enabled || want_lldb { if !target.contains("windows") { if target.contains("apple") { cfg.define("CMAKE_EXE_LINKER_FLAGS", "-static-libstdc++"); @@ -186,7 +217,7 @@ impl Step for Llvm { enabled_llvm_projects.push("compiler-rt"); } - if builder.config.lldb_enabled { + if want_lldb { enabled_llvm_projects.push("clang"); enabled_llvm_projects.push("lldb"); // For the time being, disable code signing. @@ -211,9 +242,10 @@ impl Step for Llvm { } // http://llvm.org/docs/HowToCrossCompileLLVM.html - if target != builder.config.build { + if target != builder.config.build && !emscripten { builder.ensure(Llvm { target: builder.config.build, + emscripten: false, }); // FIXME: if the llvm root for the build triple is overridden then we // should use llvm-tblgen from there, also should verify that it @@ -457,6 +489,7 @@ impl Step for Lld { let llvm_config = builder.ensure(Llvm { target: self.target, + emscripten: false, }); let out_dir = builder.lld_out(target); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 7ed67c6c7c5d5..b7ce9c7b39709 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -427,7 +427,7 @@ impl Step for Miri { // (We do this separately from the above so that when the setup actually // happens we get some output.) // We re-use the `cargo` from above. - cargo.arg("--print-sysroot"); + cargo.arg("--env"); // FIXME: Is there a way in which we can re-use the usual `run` helpers? let miri_sysroot = if builder.config.dry_run { @@ -437,11 +437,13 @@ impl Step for Miri { let out = cargo.output() .expect("We already ran `cargo miri setup` before and that worked"); assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code"); - // Output is "\n". + // Output is "MIRI_SYSROOT=\n". let stdout = String::from_utf8(out.stdout) .expect("`cargo miri setup` stdout is not valid UTF-8"); - let sysroot = stdout.trim_end(); - builder.verbose(&format!("`cargo miri setup --print-sysroot` said: {:?}", sysroot)); + let stdout = stdout.trim(); + builder.verbose(&format!("`cargo miri setup --env` returned: {:?}", stdout)); + let sysroot = stdout.splitn(2, '=') + .nth(1).expect("`cargo miri setup` stdout did not contain '='"); sysroot.to_owned() }; @@ -1045,11 +1047,10 @@ impl Step for Compiletest { // Also provide `rust_test_helpers` for the host. builder.ensure(native::TestHelpers { target: compiler.host }); - // As well as the target, except for plain wasm32, which can't build it - if !target.contains("wasm32") || target.contains("emscripten") { + // wasm32 can't build the test helpers + if !target.contains("wasm32") { builder.ensure(native::TestHelpers { target }); } - builder.ensure(RemoteCopyLibs { compiler, target }); let mut cmd = builder.tool_cmd(Tool::Compiletest); @@ -1163,7 +1164,7 @@ impl Step for Compiletest { }).to_string() }) }; - let lldb_exe = if builder.config.lldb_enabled { + let lldb_exe = if builder.config.lldb_enabled && !target.contains("emscripten") { // Test against the lldb that was just built. builder.llvm_out(target).join("bin").join("lldb") } else { @@ -1232,6 +1233,7 @@ impl Step for Compiletest { if builder.config.llvm_enabled() { let llvm_config = builder.ensure(native::Llvm { target: builder.config.build, + emscripten: false, }); if !builder.config.dry_run { let llvm_version = output(Command::new(&llvm_config).arg("--version")); diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index bb94fb2b755f5..f035a7119188a 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -21,13 +21,6 @@ macro_rules! t { Err(e) => panic!("{} failed with {}", stringify!($e), e), } }; - // it can show extra info in the second parameter - ($e:expr, $extra:expr) => { - match $e { - Ok(e) => e, - Err(e) => panic!("{} failed with {} ({:?})", stringify!($e), e, $extra), - } - }; } // Because Cargo adds the compiler's dylib path to our library search path, llvm-config may diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml index 4442afc98e406..5f7761297095c 100644 --- a/src/ci/azure-pipelines/auto.yml +++ b/src/ci/azure-pipelines/auto.yml @@ -124,14 +124,14 @@ jobs: IMAGE: dist-x86_64-netbsd DEPLOY: 1 + asmjs: + IMAGE: asmjs i686-gnu: IMAGE: i686-gnu i686-gnu-nopt: IMAGE: i686-gnu-nopt test-various: IMAGE: test-various - wasm32: - IMAGE: wasm32 x86_64-gnu: IMAGE: x86_64-gnu x86_64-gnu-full-bootstrap: 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 812339900fe42..bd4f1ed0cea43 100644 --- a/src/ci/azure-pipelines/steps/install-windows-build-deps.yml +++ b/src/ci/azure-pipelines/steps/install-windows-build-deps.yml @@ -84,17 +84,6 @@ steps: condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['MINGW_URL'],'')) displayName: Download custom MinGW -# FIXME(#65767): workaround msys bug, step 1 -- bash: | - set -e - arch=i686 - if [ "$MSYS_BITS" = "64" ]; then - arch=x86_64 - fi - curl -O https://ci-mirrors.rust-lang.org/rustc/msys2-repo/mingw/$arch/mingw-w64-$arch-ca-certificates-20180409-1-any.pkg.tar.xz - condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) - displayName: Download working ca-certificates for msys - # Otherwise install MinGW through `pacman` - bash: | set -e @@ -107,18 +96,6 @@ steps: condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],'')) displayName: Download standard MinGW -# FIXME(#65767): workaround msys bug, step 2 -- bash: | - set -e - arch=i686 - if [ "$MSYS_BITS" = "64" ]; then - arch=x86_64 - fi - pacman -U --noconfirm --noprogressbar mingw-w64-$arch-ca-certificates-20180409-1-any.pkg.tar.xz - rm mingw-w64-$arch-ca-certificates-20180409-1-any.pkg.tar.xz - condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) - displayName: Install working ca-certificates for msys - # 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 diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index a2d83eca24b0a..367e43849923f 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -165,7 +165,8 @@ 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 only +- Path and misc options > Patches origin = Bundled, then local +- Path and misc options > Local patch directory = /tmp/patches - Target options > Target Architecture = arm - Target options > Suffix to the arch-part = v7 - Target options > Architecture level = armv7-a -- (+) @@ -173,9 +174,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.101 -- C-library > glibc version = 2.17.0 -- C compiler > gcc version = 8.3.0 +- Operating System > Linux kernel version = 3.2.72 -- Precise kernel +- C-library > glibc version = 2.16.0 +- C compiler > gcc version = 5.2.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/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile new file mode 100644 index 0000000000000..3abaab6b34ef0 --- /dev/null +++ b/src/ci/docker/asmjs/Dockerfile @@ -0,0 +1,47 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils + +COPY scripts/emscripten.sh /scripts/ +RUN bash /scripts/emscripten.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV PATH=$PATH:/emsdk-portable +ENV PATH=$PATH:/emsdk-portable/clang/e1.38.15_64bit/ +ENV PATH=$PATH:/emsdk-portable/emscripten/1.38.15/ +ENV PATH=$PATH:/emsdk-portable/node/8.9.1_64bit/bin/ +ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.38.15/ +ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.38.15_64bit/binaryen/ +ENV EM_CONFIG=/emsdk-portable/.emscripten + +ENV TARGETS=asmjs-unknown-emscripten + +ENV RUST_CONFIGURE_ARGS --enable-emscripten --disable-optimize-tests + +ENV SCRIPT python2.7 ../x.py test --target $TARGETS \ + src/test/ui \ + src/test/run-fail \ + src/libstd \ + src/liballoc \ + src/libcore + +# Debug assertions in rustc are largely covered by other builders, and LLVM +# assertions cause this builder to slow down by quite a large amount and don't +# buy us a huge amount over other builders (not sure if we've ever seen an +# asmjs-specific backend assertion trip), so disable assertions for these +# tests. +ENV NO_LLVM_ASSERTIONS=1 +ENV NO_DEBUG_ASSERTIONS=1 diff --git a/src/ci/docker/disabled/asmjs/Dockerfile b/src/ci/docker/disabled/asmjs/Dockerfile deleted file mode 100644 index e27a2a529a8ca..0000000000000 --- a/src/ci/docker/disabled/asmjs/Dockerfile +++ /dev/null @@ -1,41 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - make \ - file \ - curl \ - ca-certificates \ - python \ - git \ - cmake \ - sudo \ - gdb \ - xz-utils \ - bzip2 - -COPY scripts/emscripten.sh /scripts/ -RUN bash /scripts/emscripten.sh - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -ENV PATH=$PATH:/emsdk-portable -ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/ -ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/ -ENV BINARYEN_ROOT=/emsdk-portable/upstream/ - -ENV TARGETS=asmjs-unknown-emscripten - -# Use -O1 optimizations in the link step to reduce time spent optimizing JS. -ENV EMCC_CFLAGS=-O1 - -# Emscripten installation is user-specific -ENV NO_CHANGE_USER=1 - -ENV SCRIPT python2.7 ../x.py test --target $TARGETS - -# This is almost identical to the wasm32-unknown-emscripten target, so -# running with assertions again is not useful -ENV NO_DEBUG_ASSERTIONS=1 -ENV NO_LLVM_ASSERTIONS=1 diff --git a/src/ci/docker/disabled/wasm32-exp/Dockerfile b/src/ci/docker/disabled/wasm32-exp/Dockerfile new file mode 100644 index 0000000000000..420d47b314c0f --- /dev/null +++ b/src/ci/docker/disabled/wasm32-exp/Dockerfile @@ -0,0 +1,35 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils \ + jq \ + bzip2 + +# emscripten +COPY scripts/emscripten-wasm.sh /scripts/ +COPY wasm32-exp/node.sh /usr/local/bin/node +RUN bash /scripts/emscripten-wasm.sh + +# cache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# env +ENV PATH=/wasm-install/emscripten:/wasm-install/bin:$PATH +ENV EM_CONFIG=/root/.emscripten + +ENV TARGETS=wasm32-experimental-emscripten + +ENV RUST_CONFIGURE_ARGS --experimental-targets=WebAssembly + +ENV SCRIPT python2.7 ../x.py test --target $TARGETS diff --git a/src/ci/docker/disabled/wasm32-exp/node.sh b/src/ci/docker/disabled/wasm32-exp/node.sh new file mode 100755 index 0000000000000..aa938971c702f --- /dev/null +++ b/src/ci/docker/disabled/wasm32-exp/node.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +path="$(dirname $1)" +file="$(basename $1)" + +shift + +cd "$path" +exec /node-v8.0.0-linux-x64/bin/node "$file" "$@" diff --git a/src/ci/docker/disabled/wasm32/Dockerfile b/src/ci/docker/disabled/wasm32/Dockerfile new file mode 100644 index 0000000000000..0d2bd39303ef8 --- /dev/null +++ b/src/ci/docker/disabled/wasm32/Dockerfile @@ -0,0 +1,32 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils + +# emscripten +COPY scripts/emscripten.sh /scripts/ +RUN bash /scripts/emscripten.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV PATH=$PATH:/emsdk-portable +ENV PATH=$PATH:/emsdk-portable/clang/e1.38.15_64bit/ +ENV PATH=$PATH:/emsdk-portable/emscripten/1.38.15/ +ENV PATH=$PATH:/emsdk-portable/node/8.9.1_64bit/bin/ +ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.38.15/ +ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.38.15_64bit/binaryen/ +ENV EM_CONFIG=/emsdk-portable/.emscripten + +ENV TARGETS=wasm32-unknown-emscripten +ENV SCRIPT python2.7 ../x.py test --target $TARGETS diff --git a/src/ci/docker/dist-armv7-linux/Dockerfile b/src/ci/docker/dist-armv7-linux/Dockerfile index 417171a861d4a..170b8134d3edc 100644 --- a/src/ci/docker/dist-armv7-linux/Dockerfile +++ b/src/ci/docker/dist-armv7-linux/Dockerfile @@ -3,7 +3,12 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY dist-armv7-linux/crosstool-ng.sh /scripts/ +# 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/ RUN sh /scripts/crosstool-ng.sh COPY scripts/rustbuild-setup.sh /scripts/ @@ -11,6 +16,7 @@ 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 81b3d7477ec8d..5cccfd8444d35 100644 --- a/src/ci/docker/dist-armv7-linux/armv7-linux-gnueabihf.config +++ b/src/ci/docker/dist-armv7-linux/armv7-linux-gnueabihf.config @@ -1,32 +1,9 @@ # # Automatically generated file; DO NOT EDIT. -# 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" +# Crosstool-NG Configuration +# +CT_CONFIGURE_has_make381=y +CT_CONFIGURE_has_xz=y CT_MODULES=y # @@ -44,46 +21,40 @@ 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_LICENSES=y -CT_PREFIX_DIR_RO=y +CT_INSTALL_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_OVERRIDE_CONFIG_GUESS_SUB=y +CT_OVERIDE_CONFIG_GUESS_SUB=y # CT_ONLY_EXTRACT is not set -CT_PATCH_BUNDLED=y -# CT_PATCH_BUNDLED_LOCAL is not set -CT_PATCH_ORDER="bundled" +# 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" # # Build behavior @@ -119,81 +90,86 @@ 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_CHOICE_KSYM="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_CPU="" CT_ARCH_TUNE="" -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_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_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 # @@ -206,9 +182,7 @@ 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="" @@ -242,207 +216,126 @@ 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_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" +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_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 + # # Binary utilities # CT_ARCH_BINFMT_ELF=y -CT_BINUTILS_BINUTILS=y CT_BINUTILS="binutils" -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 +CT_BINUTILS_binutils=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_HAS_PLUGINS=y -CT_BINUTILS_HAS_PKGVERSION_BUGURL=y CT_BINUTILS_GOLD_SUPPORTS_ARCH=y CT_BINUTILS_GOLD_SUPPORT=y -CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y +CT_BINUTILS_HAS_PLUGINS=y +CT_BINUTILS_HAS_PKGVERSION_BUGURL=y +CT_BINUTILS_FORCE_LD_BFD=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 -CT_ALL_BINUTILS_CHOICES="BINUTILS" + +# +# binutils other options +# # # C-library # -CT_LIBC_GLIBC=y -# CT_LIBC_UCLIBC is not set CT_LIBC="glibc" -CT_LIBC_CHOICE_KSYM="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_THREADS="nptl" -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_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_SUPPORT_THREADS_ANY=y CT_LIBC_SUPPORT_THREADS_NATIVE=y @@ -450,71 +343,100 @@ 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_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=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_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 @@ -543,206 +465,97 @@ 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_ALL_CC_CHOICES="GCC" +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 # # Additional supported languages: # CT_CC_LANG_CXX=y -# CT_CC_LANG_FORTRAN is not set +# CT_CC_LANG_JAVA is not set # # Debug facilities # -# 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" +# 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 # # Companion libraries # -# 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_COMPLIBS_NEEDED=y 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_NCURSES_NEEDED=y -CT_ZLIB_NEEDED=y +CT_COMPLIBS=y CT_LIBICONV=y CT_GETTEXT=y CT_GMP=y CT_MPFR=y CT_ISL=y CT_MPC=y -CT_NCURSES=y -CT_ZLIB=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 # # Companion tools # -# 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" + +# +# READ HELP before you say 'Y' below !!! +# +# CT_COMP_TOOLS is not set diff --git a/src/ci/docker/dist-armv7-linux/crosstool-ng.sh b/src/ci/docker/dist-armv7-linux/crosstool-ng.sh deleted file mode 100644 index ae737d9677d87..0000000000000 --- a/src/ci/docker/dist-armv7-linux/crosstool-ng.sh +++ /dev/null @@ -1,12 +0,0 @@ -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 new file mode 100644 index 0000000000000..871d5225c0f71 --- /dev/null +++ b/src/ci/docker/dist-armv7-linux/patches/glibc/ports-2.16.0/001-arm-libgcc_s_resume-used.patch @@ -0,0 +1,48 @@ +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-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index fab3824a20ae3..105791194628b 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -139,6 +139,7 @@ ENV RUST_CONFIGURE_ARGS \ --musl-root-aarch64=/musl-aarch64 \ --musl-root-mips=/musl-mips \ --musl-root-mipsel=/musl-mipsel \ + --enable-emscripten \ --disable-docs ENV SCRIPT \ 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 8200bbe2fdce5..fb8b63d7920b1 100755 --- a/src/ci/docker/dist-x86_64-linux/build-curl.sh +++ b/src/ci/docker/dist-x86_64-linux/build-curl.sh @@ -3,11 +3,9 @@ set -ex source shared.sh -VERSION=7.66.0 +VERSION=7.51.0 -curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/curl-$VERSION.tar.xz \ - | xz --decompress \ - | tar xf - +curl http://cool.haxx.se/download/curl-$VERSION.tar.bz2 | tar xjf - mkdir curl-build cd curl-build diff --git a/src/ci/docker/scripts/cross-apt-packages.sh b/src/ci/docker/scripts/cross-apt-packages.sh index bb72e33def21c..51945fd72adc7 100644 --- a/src/ci/docker/scripts/cross-apt-packages.sh +++ b/src/ci/docker/scripts/cross-apt-packages.sh @@ -22,6 +22,5 @@ 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/emscripten-wasm.sh b/src/ci/docker/scripts/emscripten-wasm.sh new file mode 100644 index 0000000000000..e4a93d7a10092 --- /dev/null +++ b/src/ci/docker/scripts/emscripten-wasm.sh @@ -0,0 +1,37 @@ +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + rm -f /tmp/build.log + set -x +} + +# Download last known good emscripten from WebAssembly waterfall +BUILD=$(curl -fL https://storage.googleapis.com/wasm-llvm/builds/linux/lkgr.json | \ + jq '.build | tonumber') +curl -sL https://storage.googleapis.com/wasm-llvm/builds/linux/$BUILD/wasm-binaries.tbz2 | \ + hide_output tar xvkj + +# node 8 is required to run wasm +cd / +curl -sL https://nodejs.org/dist/v8.0.0/node-v8.0.0-linux-x64.tar.xz | \ + tar -xJ + +# Make emscripten use wasm-ready node and LLVM tools +echo "EMSCRIPTEN_ROOT = '/wasm-install/emscripten'" >> /root/.emscripten +echo "NODE_JS='/usr/local/bin/node'" >> /root/.emscripten +echo "LLVM_ROOT='/wasm-install/bin'" >> /root/.emscripten +echo "BINARYEN_ROOT = '/wasm-install'" >> /root/.emscripten +echo "COMPILER_ENGINE = NODE_JS" >> /root/.emscripten +echo "JS_ENGINES = [NODE_JS]" >> /root/.emscripten diff --git a/src/ci/docker/scripts/emscripten.sh b/src/ci/docker/scripts/emscripten.sh index 1be80741594cc..47196e8939626 100644 --- a/src/ci/docker/scripts/emscripten.sh +++ b/src/ci/docker/scripts/emscripten.sh @@ -17,7 +17,22 @@ exit 1 set -x } -git clone https://github.com/emscripten-core/emsdk.git /emsdk-portable +cd / +curl -fL https://mozilla-games.s3.amazonaws.com/emscripten/releases/emsdk-portable.tar.gz | \ + tar -xz + cd /emsdk-portable -hide_output ./emsdk install 1.38.46-upstream -./emsdk activate 1.38.46-upstream +./emsdk update +hide_output ./emsdk install sdk-1.38.15-64bit +./emsdk activate sdk-1.38.15-64bit + +# Compile and cache libc +source ./emsdk_env.sh +echo "main(){}" > a.c +HOME=/emsdk-portable/ emcc a.c +HOME=/emsdk-portable/ emcc -s BINARYEN=1 a.c +rm -f a.* + +# Make emsdk usable by any user +cp /root/.emscripten /emsdk-portable +chmod a+rxw -R /emsdk-portable diff --git a/src/ci/docker/wasm32/Dockerfile b/src/ci/docker/wasm32/Dockerfile deleted file mode 100644 index a0f35afd995b3..0000000000000 --- a/src/ci/docker/wasm32/Dockerfile +++ /dev/null @@ -1,44 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - make \ - file \ - curl \ - ca-certificates \ - python \ - git \ - cmake \ - sudo \ - gdb \ - xz-utils \ - bzip2 - -COPY scripts/emscripten.sh /scripts/ -RUN bash /scripts/emscripten.sh - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -ENV PATH=$PATH:/emsdk-portable -ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/ -ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/ -ENV BINARYEN_ROOT=/emsdk-portable/upstream/ - -ENV TARGETS=wasm32-unknown-emscripten - -# Use -O1 optimizations in the link step to reduce time spent optimizing. -ENV EMCC_CFLAGS=-O1 - -# Emscripten installation is user-specific -ENV NO_CHANGE_USER=1 - -# FIXME: Re-enable these tests once https://github.com/rust-lang/cargo/pull/7476 -# is picked up by CI -ENV SCRIPT python2.7 ../x.py test --target $TARGETS \ - --exclude src/libcore \ - --exclude src/liballoc \ - --exclude src/libproc_macro \ - --exclude src/libstd \ - --exclude src/libterm \ - --exclude src/libtest diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh index 92c6e546a3895..c7c3b0a5fbf5b 100755 --- a/src/ci/init_repo.sh +++ b/src/ci/init_repo.sh @@ -47,7 +47,7 @@ function fetch_github_commit_archive { rm $cached } -included="src/llvm-project src/doc/book src/doc/rust-by-example" +included="src/llvm-project src/llvm-emscripten src/doc/book src/doc/rust-by-example" modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)" modules=($modules) use_git="" diff --git a/src/ci/run.sh b/src/ci/run.sh index 0d5ea371245e4..457ba97171207 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -55,9 +55,6 @@ if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions" elif [ "$DEPLOY_ALT" != "" ]; then - if [ "$NO_PARALLEL_COMPILER" = "" ]; then - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.parallel-compiler" - fi RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-assertions" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.verify-llvm-ir" fi diff --git a/src/doc/book b/src/doc/book index 9bb8b161963fc..871416b85c1a7 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 9bb8b161963fcebc9d9ccd732ba26f42108016d5 +Subproject commit 871416b85c1a73717d65d6f4a9ea29e5aef3db0e diff --git a/src/doc/grammar.md b/src/doc/grammar.md index 4501d74073e90..ee9135b6578f6 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -1,7 +1,812 @@ % Grammar -The Rust grammar may now be found in the [reference]. Additionally, the [grammar -working group] is working on producing a testable grammar. +# Introduction -[reference]: https://doc.rust-lang.org/reference/ -[grammar working group]: https://github.com/rust-lang/wg-grammar +This document is the primary reference for the Rust programming language grammar. It +provides only one kind of material: + + - Chapters that formally define the language grammar. + +This document does not serve as an introduction to the language. Background +familiarity with the language is assumed. A separate [guide] is available to +help acquire such background. + +This document also does not serve as a reference to the [standard] library +included in the language distribution. Those libraries are documented +separately by extracting documentation attributes from their source code. Many +of the features that one might expect to be language features are library +features in Rust, so what you're looking for may be there, not here. + +[guide]: guide.html +[standard]: std/index.html + +# Notation + +Rust's grammar is defined over Unicode codepoints, each conventionally denoted +`U+XXXX`, for 4 or more hexadecimal digits `X`. _Most_ of Rust's grammar is +confined to the ASCII range of Unicode, and is described in this document by a +dialect of Extended Backus-Naur Form (EBNF), specifically a dialect of EBNF +supported by common automated LL(k) parsing tools such as `llgen`, rather than +the dialect given in ISO 14977. The dialect can be defined self-referentially +as follows: + +```antlr +grammar : rule + ; +rule : nonterminal ':' productionrule ';' ; +productionrule : production [ '|' production ] * ; +production : term * ; +term : element repeats ; +element : LITERAL | IDENTIFIER | '[' productionrule ']' ; +repeats : [ '*' | '+' ] NUMBER ? | NUMBER ? | '?' ; +``` + +Where: + +- Whitespace in the grammar is ignored. +- Square brackets are used to group rules. +- `LITERAL` is a single printable ASCII character, or an escaped hexadecimal + ASCII code of the form `\xQQ`, in single quotes, denoting the corresponding + Unicode codepoint `U+00QQ`. +- `IDENTIFIER` is a nonempty string of ASCII letters and underscores. +- The `repeat` forms apply to the adjacent `element`, and are as follows: + - `?` means zero or one repetition + - `*` means zero or more repetitions + - `+` means one or more repetitions + - NUMBER trailing a repeat symbol gives a maximum repetition count + - NUMBER on its own gives an exact repetition count + +This EBNF dialect should hopefully be familiar to many readers. + +## Unicode productions + +A few productions in Rust's grammar permit Unicode codepoints outside the ASCII +range. We define these productions in terms of character properties specified +in the Unicode standard, rather than in terms of ASCII-range codepoints. The +section [Special Unicode Productions](#special-unicode-productions) lists these +productions. + +## String table productions + +Some rules in the grammar — notably [unary +operators](#unary-operator-expressions), [binary +operators](#binary-operator-expressions), and [keywords](#keywords) — are +given in a simplified form: as a listing of a table of unquoted, printable +whitespace-separated strings. These cases form a subset of the rules regarding +the [token](#tokens) rule, and are assumed to be the result of a +lexical-analysis phase feeding the parser, driven by a DFA, operating over the +disjunction of all such string table entries. + +When such a string enclosed in double-quotes (`"`) occurs inside the grammar, +it is an implicit reference to a single member of such a string table +production. See [tokens](#tokens) for more information. + +# Lexical structure + +## Input format + +Rust input is interpreted as a sequence of Unicode codepoints encoded in UTF-8. +Most Rust grammar rules are defined in terms of printable ASCII-range +codepoints, but a small number are defined in terms of Unicode properties or +explicit codepoint lists. [^inputformat] + +[^inputformat]: Substitute definitions for the special Unicode productions are + provided to the grammar verifier, restricted to ASCII range, when verifying the + grammar in this document. + +## Special Unicode Productions + +The following productions in the Rust grammar are defined in terms of Unicode +properties: `ident`, `non_null`, `non_eol`, `non_single_quote` and +`non_double_quote`. + +### Identifiers + +The `ident` production is any nonempty Unicode string of +the following form: + +- The first character is in one of the following ranges `U+0041` to `U+005A` +("A" to "Z"), `U+0061` to `U+007A` ("a" to "z"), or `U+005F` ("\_"). +- The remaining characters are in the range `U+0030` to `U+0039` ("0" to "9"), +or any of the prior valid initial characters. + +as long as the identifier does _not_ occur in the set of [keywords](#keywords). + +### Delimiter-restricted productions + +Some productions are defined by exclusion of particular Unicode characters: + +- `non_null` is any single Unicode character aside from `U+0000` (null) +- `non_eol` is any single Unicode character aside from `U+000A` (`'\n'`) +- `non_single_quote` is any single Unicode character aside from `U+0027` (`'`) +- `non_double_quote` is any single Unicode character aside from `U+0022` (`"`) + +## Comments + +```antlr +comment : block_comment | line_comment ; +block_comment : "/*" block_comment_body * "*/" ; +block_comment_body : [block_comment | character] * ; +line_comment : "//" non_eol * ; +``` + +**FIXME:** add doc grammar? + +## Whitespace + +```antlr +whitespace_char : '\x20' | '\x09' | '\x0a' | '\x0d' ; +whitespace : [ whitespace_char | comment ] + ; +``` + +## Tokens + +```antlr +simple_token : keyword | unop | binop ; +token : simple_token | ident | literal | symbol | whitespace token ; +``` + +### Keywords + +

+ +| | | | | | +|----------|----------|----------|----------|----------| +| _ | abstract | alignof | as | become | +| box | break | const | continue | crate | +| do | else | enum | extern | false | +| final | fn | for | if | impl | +| in | let | loop | macro | match | +| mod | move | mut | offsetof | override | +| priv | proc | pub | pure | ref | +| return | Self | self | sizeof | static | +| struct | super | trait | true | type | +| typeof | unsafe | unsized | use | virtual | +| where | while | yield | | | + + +Each of these keywords has special meaning in its grammar, and all of them are +excluded from the `ident` rule. + +Not all of these keywords are used by the language. Some of them were used +before Rust 1.0, and were left reserved once their implementations were +removed. Some of them were reserved before 1.0 to make space for possible +future features. + +### Literals + +```antlr +lit_suffix : ident; +literal : [ string_lit | char_lit | byte_string_lit | byte_lit | num_lit | bool_lit ] lit_suffix ?; +``` + +The optional `lit_suffix` production is only used for certain numeric literals, +but is reserved for future extension. That is, the above gives the lexical +grammar, but a Rust parser will reject everything but the 12 special cases +mentioned in [Number literals](reference/tokens.html#number-literals) in the +reference. + +#### Character and string literals + +```antlr +char_lit : '\x27' char_body '\x27' ; +string_lit : '"' string_body * '"' | 'r' raw_string ; + +char_body : non_single_quote + | '\x5c' [ '\x27' | common_escape | unicode_escape ] ; + +string_body : non_double_quote + | '\x5c' [ '\x22' | common_escape | unicode_escape ] ; +raw_string : '"' raw_string_body '"' | '#' raw_string '#' ; + +common_escape : '\x5c' + | 'n' | 'r' | 't' | '0' + | 'x' hex_digit 2 +unicode_escape : 'u' '{' hex_digit+ 6 '}'; + +hex_digit : 'a' | 'b' | 'c' | 'd' | 'e' | 'f' + | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' + | dec_digit ; +oct_digit : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' ; +dec_digit : '0' | nonzero_dec ; +nonzero_dec: '1' | '2' | '3' | '4' + | '5' | '6' | '7' | '8' | '9' ; +``` + +#### Byte and byte string literals + +```antlr +byte_lit : "b\x27" byte_body '\x27' ; +byte_string_lit : "b\x22" string_body * '\x22' | "br" raw_byte_string ; + +byte_body : ascii_non_single_quote + | '\x5c' [ '\x27' | common_escape ] ; + +byte_string_body : ascii_non_double_quote + | '\x5c' [ '\x22' | common_escape ] ; +raw_byte_string : '"' raw_byte_string_body '"' | '#' raw_byte_string '#' ; + +``` + +#### Number literals + +```antlr +num_lit : nonzero_dec [ dec_digit | '_' ] * float_suffix ? + | '0' [ [ dec_digit | '_' ] * float_suffix ? + | 'b' [ '1' | '0' | '_' ] + + | 'o' [ oct_digit | '_' ] + + | 'x' [ hex_digit | '_' ] + ] ; + +float_suffix : [ exponent | '.' dec_lit exponent ? ] ? ; + +exponent : ['E' | 'e'] ['-' | '+' ] ? dec_lit ; +dec_lit : [ dec_digit | '_' ] + ; +``` + +#### Boolean literals + +```antlr +bool_lit : [ "true" | "false" ] ; +``` + +The two values of the boolean type are written `true` and `false`. + +### Symbols + +```antlr +symbol : "::" | "->" + | '#' | '[' | ']' | '(' | ')' | '{' | '}' + | ',' | ';' ; +``` + +Symbols are a general class of printable [tokens](#tokens) that play structural +roles in a variety of grammar productions. They are cataloged here for +completeness as the set of remaining miscellaneous printable tokens that do not +otherwise appear as [unary operators](#unary-operator-expressions), [binary +operators](#binary-operator-expressions), or [keywords](#keywords). + +## Paths + +```antlr +expr_path : [ "::" ] ident [ "::" expr_path_tail ] + ; +expr_path_tail : '<' type_expr [ ',' type_expr ] + '>' + | expr_path ; + +type_path : ident [ type_path_tail ] + ; +type_path_tail : '<' type_expr [ ',' type_expr ] + '>' + | "::" type_path ; +``` + +# Syntax extensions + +## Macros + +```antlr +expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')' ';' + | "macro_rules" '!' ident '{' macro_rule * '}' ; +macro_rule : '(' matcher * ')' "=>" '(' transcriber * ')' ';' ; +matcher : '(' matcher * ')' | '[' matcher * ']' + | '{' matcher * '}' | '$' ident ':' ident + | '$' '(' matcher * ')' sep_token? [ '*' | '+' ] + | non_special_token ; +transcriber : '(' transcriber * ')' | '[' transcriber * ']' + | '{' transcriber * '}' | '$' ident + | '$' '(' transcriber * ')' sep_token? [ '*' | '+' ] + | non_special_token ; +``` + +# Crates and source files + +**FIXME:** grammar? What production covers #![crate_id = "foo"] ? + +# Items and attributes + +**FIXME:** grammar? + +## Items + +```antlr +item : vis ? mod_item | fn_item | type_item | struct_item | enum_item + | const_item | static_item | trait_item | impl_item | extern_block_item ; +``` + +### Type Parameters + +**FIXME:** grammar? + +### Modules + +```antlr +mod_item : "mod" ident ( ';' | '{' mod '}' ); +mod : [ view_item | item ] * ; +``` + +#### View items + +```antlr +view_item : extern_crate_decl | use_decl ';' ; +``` + +##### Extern crate declarations + +```antlr +extern_crate_decl : "extern" "crate" crate_name +crate_name: ident | ( ident "as" ident ) +``` + +##### Use declarations + +```antlr +use_decl : vis ? "use" [ path "as" ident + | path_glob ] ; + +path_glob : ident [ "::" [ path_glob + | '*' ] ] ? + | '{' path_item [ ',' path_item ] * '}' ; + +path_item : ident | "self" ; +``` + +### Functions + +**FIXME:** grammar? + +#### Generic functions + +**FIXME:** grammar? + +#### Unsafety + +**FIXME:** grammar? + +##### Unsafe functions + +**FIXME:** grammar? + +##### Unsafe blocks + +**FIXME:** grammar? + +#### Diverging functions + +**FIXME:** grammar? + +### Type definitions + +**FIXME:** grammar? + +### Structures + +**FIXME:** grammar? + +### Enumerations + +**FIXME:** grammar? + +### Constant items + +```antlr +const_item : "const" ident ':' type '=' expr ';' ; +``` + +### Static items + +```antlr +static_item : "static" ident ':' type '=' expr ';' ; +``` + +#### Mutable statics + +**FIXME:** grammar? + +### Traits + +**FIXME:** grammar? + +### Implementations + +**FIXME:** grammar? + +### External blocks + +```antlr +extern_block_item : "extern" '{' extern_block '}' ; +extern_block : [ foreign_fn ] * ; +``` + +## Visibility and Privacy + +```antlr +vis : "pub" ; +``` +### Re-exporting and Visibility + +See [Use declarations](#use-declarations). + +## Attributes + +```antlr +attribute : '#' '!' ? '[' meta_item ']' ; +meta_item : ident [ '=' literal + | '(' meta_seq ')' ] ? ; +meta_seq : meta_item [ ',' meta_seq ] ? ; +``` + +# Statements and expressions + +## Statements + +```antlr +stmt : decl_stmt | expr_stmt | ';' ; +``` + +### Declaration statements + +```antlr +decl_stmt : item | let_decl ; +``` + +#### Item declarations + +See [Items](#items). + +#### Variable declarations + +```antlr +let_decl : "let" pat [':' type ] ? [ init ] ? ';' ; +init : [ '=' ] expr ; +``` + +### Expression statements + +```antlr +expr_stmt : expr ';' ; +``` + +## Expressions + +```antlr +expr : literal | path | tuple_expr | unit_expr | struct_expr + | block_expr | method_call_expr | field_expr | array_expr + | idx_expr | range_expr | unop_expr | binop_expr + | paren_expr | call_expr | lambda_expr | while_expr + | loop_expr | break_expr | continue_expr | for_expr + | if_expr | match_expr | if_let_expr | while_let_expr + | return_expr ; +``` + +#### Lvalues, rvalues and temporaries + +**FIXME:** grammar? + +#### Moved and copied types + +**FIXME:** Do we want to capture this in the grammar as different productions? + +### Literal expressions + +See [Literals](#literals). + +### Path expressions + +See [Paths](#paths). + +### Tuple expressions + +```antlr +tuple_expr : '(' [ expr [ ',' expr ] * | expr ',' ] ? ')' ; +``` + +### Unit expressions + +```antlr +unit_expr : "()" ; +``` + +### Structure expressions + +```antlr +struct_expr_field_init : ident | ident ':' expr ; +struct_expr : expr_path '{' struct_expr_field_init + [ ',' struct_expr_field_init ] * + [ ".." expr ] '}' | + expr_path '(' expr + [ ',' expr ] * ')' | + expr_path ; +``` + +### Block expressions + +```antlr +block_expr : '{' [ stmt | item ] * + [ expr ] '}' ; +``` + +### Method-call expressions + +```antlr +method_call_expr : expr '.' ident paren_expr_list ; +``` + +### Field expressions + +```antlr +field_expr : expr '.' ident ; +``` + +### Array expressions + +```antlr +array_expr : '[' "mut" ? array_elems? ']' ; + +array_elems : [expr [',' expr]*] | [expr ';' expr] ; +``` + +### Index expressions + +```antlr +idx_expr : expr '[' expr ']' ; +``` + +### Range expressions + +```antlr +range_expr : expr ".." expr | + expr ".." | + ".." expr | + ".." ; +``` + +### Unary operator expressions + +```antlr +unop_expr : unop expr ; +unop : '-' | '*' | '!' ; +``` + +### Binary operator expressions + +```antlr +binop_expr : expr binop expr | type_cast_expr + | assignment_expr | compound_assignment_expr ; +binop : arith_op | bitwise_op | lazy_bool_op | comp_op +``` + +#### Arithmetic operators + +```antlr +arith_op : '+' | '-' | '*' | '/' | '%' ; +``` + +#### Bitwise operators + +```antlr +bitwise_op : '&' | '|' | '^' | "<<" | ">>" ; +``` + +#### Lazy boolean operators + +```antlr +lazy_bool_op : "&&" | "||" ; +``` + +#### Comparison operators + +```antlr +comp_op : "==" | "!=" | '<' | '>' | "<=" | ">=" ; +``` + +#### Type cast expressions + +```antlr +type_cast_expr : value "as" type ; +``` + +#### Assignment expressions + +```antlr +assignment_expr : expr '=' expr ; +``` + +#### Compound assignment expressions + +```antlr +compound_assignment_expr : expr [ arith_op | bitwise_op ] '=' expr ; +``` + +### Grouped expressions + +```antlr +paren_expr : '(' expr ')' ; +``` + +### Call expressions + +```antlr +expr_list : [ expr [ ',' expr ]* ] ? ; +paren_expr_list : '(' expr_list ')' ; +call_expr : expr paren_expr_list ; +``` + +### Lambda expressions + +```antlr +ident_list : [ ident [ ',' ident ]* ] ? ; +lambda_expr : '|' ident_list '|' expr ; +``` + +### While loops + +```antlr +while_expr : [ lifetime ':' ] ? "while" no_struct_literal_expr '{' block '}' ; +``` + +### Infinite loops + +```antlr +loop_expr : [ lifetime ':' ] ? "loop" '{' block '}'; +``` + +### Break expressions + +```antlr +break_expr : "break" [ lifetime ] ?; +``` + +### Continue expressions + +```antlr +continue_expr : "continue" [ lifetime ] ?; +``` + +### For expressions + +```antlr +for_expr : [ lifetime ':' ] ? "for" pat "in" no_struct_literal_expr '{' block '}' ; +``` + +### If expressions + +```antlr +if_expr : "if" no_struct_literal_expr '{' block '}' + else_tail ? ; + +else_tail : "else" [ if_expr | if_let_expr + | '{' block '}' ] ; +``` + +### Match expressions + +```antlr +match_expr : "match" no_struct_literal_expr '{' match_arm * '}' ; + +match_arm : attribute * match_pat "=>" [ expr "," | '{' block '}' ] ; + +match_pat : pat [ '|' pat ] * [ "if" expr ] ? ; +``` + +### If let expressions + +```antlr +if_let_expr : "if" "let" pat '=' expr '{' block '}' + else_tail ? ; +``` + +### While let loops + +```antlr +while_let_expr : [ lifetime ':' ] ? "while" "let" pat '=' expr '{' block '}' ; +``` + +### Return expressions + +```antlr +return_expr : "return" expr ? ; +``` + +# Type system + +**FIXME:** is this entire chapter relevant here? Or should it all have been covered by some production already? + +## Types + +### Primitive types + +**FIXME:** grammar? + +#### Machine types + +**FIXME:** grammar? + +#### Machine-dependent integer types + +**FIXME:** grammar? + +### Textual types + +**FIXME:** grammar? + +### Tuple types + +**FIXME:** grammar? + +### Array, and Slice types + +**FIXME:** grammar? + +### Structure types + +**FIXME:** grammar? + +### Enumerated types + +**FIXME:** grammar? + +### Pointer types + +**FIXME:** grammar? + +### Function types + +**FIXME:** grammar? + +### Closure types + +```antlr +closure_type := [ 'unsafe' ] [ '<' lifetime-list '>' ] '|' arg-list '|' + [ ':' bound-list ] [ '->' type ] +lifetime-list := lifetime | lifetime ',' lifetime-list +arg-list := ident ':' type | ident ':' type ',' arg-list +``` + +### Never type +An empty type + +```antlr +never_type : "!" ; +``` + +### Object types + +**FIXME:** grammar? + +### Type parameters + +**FIXME:** grammar? + +### Type parameter bounds + +```antlr +bound-list := bound | bound '+' bound-list '+' ? +bound := ty_bound | lt_bound +lt_bound := lifetime +ty_bound := ty_bound_noparen | (ty_bound_noparen) +ty_bound_noparen := [?] [ for ] simple_path +``` + +### Self types + +**FIXME:** grammar? + +## Type kinds + +**FIXME:** this is probably not relevant to the grammar... + +# Memory and concurrency models + +**FIXME:** is this entire chapter relevant here? Or should it all have been covered by some production already? + +## Memory model + +### Memory allocation and lifetime + +### Memory ownership + +### Variables + +### Boxes + +## Threads + +### Communication between threads + +### Thread lifecycle diff --git a/src/doc/nomicon b/src/doc/nomicon index 5004ad30d69f9..4374786f0b4bf 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 5004ad30d69f93553ceef74439fea2159d1f769e +Subproject commit 4374786f0b4bf0606b35d5c30a9681f342e5707b diff --git a/src/doc/reference b/src/doc/reference index 5b9d2fcefadfc..fa5dfb832ef8a 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 5b9d2fcefadfc32fceafacfc0dd9441d9b57dd94 +Subproject commit fa5dfb832ef8a7568e17dabf612f486d641ff4ac diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 0b111eaae36cc..67cfbf31df880 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 0b111eaae36cc4b4997684be853882a59e2c7ca7 +Subproject commit 67cfbf31df880728dcf7cb35b15b028ec92caf31 diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index b603c7b231e68..3cda8d927973c 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -10,11 +10,9 @@ - [Warn-by-default lints](lints/listing/warn-by-default.md) - [Deny-by-default lints](lints/listing/deny-by-default.md) - [Codegen options](codegen-options/index.md) -- [JSON Output](json.md) - [Targets](targets/index.md) - [Built-in Targets](targets/built-in.md) - [Custom Targets](targets/custom.md) - - [Known Issues](targets/known-issues.md) - [Profile-guided Optimization](profile-guided-optimization.md) - [Linker-plugin based LTO](linker-plugin-lto.md) - [Contributing to `rustc`](contributing.md) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index f5d5f2089d7e7..5c41acc6581c5 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -61,8 +61,6 @@ enabling or disabling a feature. To see the valid options and an example of use, run `rustc --print target-features`. -Using this flag is unsafe and might result in [undefined runtime behavior](../targets/known-issues.md). - ## passes This flag can be used to add extra LLVM passes to the compilation. @@ -107,7 +105,7 @@ flag will turn that behavior off. ## no-vectorize-slp -By default, `rustc` will attempt to vectorize code using [superword-level +By default, `rustc` will attempt to vectorize loops using [superword-level parallelism](https://llvm.org/docs/Vectorizers.html#the-slp-vectorizer). This flag will turn that behavior off. diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index bdb3c5196585e..5eea9c8687900 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -92,7 +92,6 @@ information about editions may be found in the [edition guide]. [edition guide]: ../edition-guide/introduction.html ## `--emit`: specifies the types of output files to generate - This flag controls the types of output files generated by the compiler. It accepts a comma-separated list of values, and may be specified multiple times. @@ -145,7 +144,7 @@ of print values are: target CPU may be selected with the `-C target-cpu=val` flag. - `target-features` — List of available target features for the current target. Target features may be enabled with the `-C target-feature=val` - flag. This flag is unsafe. See [known issues](targets/known-issues.md) for more details. + flag. - `relocation-models` — List of relocation models. Relocation models may be selected with the `-C relocation-model=val` flag. - `code-models` — List of code models. Code models may be selected with the @@ -242,13 +241,12 @@ The "sysroot" is where `rustc` looks for the crates that come with the Rust distribution; this flag allows that to be overridden. ## `--error-format`: control how errors are produced - This flag lets you control the format of messages. Messages are printed to stderr. The valid options are: - `human` — Human-readable output. This is the default. -- `json` — Structured JSON output. See [the JSON chapter] for more detail. +- `json` — Structured JSON output. - `short` — Short, one-line messages. ## `--color`: configure coloring of output @@ -275,7 +273,6 @@ pathname syntax. For example `--remap-path-prefix foo=bar` will match `foo/lib.rs` but not `./foo/lib.rs`. ## `--json`: configure json messages printed by the compiler - When the `--error-format=json` option is passed to rustc then all of the compiler's diagnostic output will be emitted in the form of JSON blobs. The @@ -308,13 +305,9 @@ 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`. -See [the JSON chapter] for more detail. - ## `@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. - -[the JSON chapter]: json.md diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md deleted file mode 100644 index b737849516310..0000000000000 --- a/src/doc/rustc/src/json.md +++ /dev/null @@ -1,231 +0,0 @@ -# JSON Output - -This chapter documents the JSON structures emitted by `rustc`. JSON may be -enabled with the [`--error-format=json` flag][option-error-format]. Additional -options may be specified with the [`--json` flag][option-json] which can -change which messages are generated, and the format of the messages. - -JSON messages are emitted one per line to stderr. - -If parsing the output with Rust, the -[`cargo_metadata`](https://crates.io/crates/cargo_metadata) crate provides -some support for parsing the messages. - -When parsing, care should be taken to be forwards-compatible with future changes -to the format. Optional values may be `null`. New fields may be added. Enumerated -fields like "level" or "suggestion_applicability" may add new values. - -## Diagnostics - -Diagnostic messages provide errors or possible concerns generated during -compilation. `rustc` provides detailed information about where the diagnostic -originates, along with hints and suggestions. - -Diagnostics are arranged in a parent/child relationship where the parent -diagnostic value is the core of the diagnostic, and the attached children -provide additional context, help, and information. - -Diagnostics have the following format: - -```javascript -{ - /* The primary message. */ - "message": "unused variable: `x`", - /* The diagnostic code. - Some messages may set this value to null. - */ - "code": { - /* A unique string identifying which diagnostic triggered. */ - "code": "unused_variables", - /* An optional string explaining more detail about the diagnostic code. */ - "explanation": null - }, - /* The severity of the diagnostic. - Values may be: - - "error": A fatal error that prevents compilation. - - "warning": A possible error or concern. - - "note": Additional information or context about the diagnostic. - - "help": A suggestion on how to resolve the diagnostic. - - "failure-note": A note attached to the message for further information. - - "error: internal compiler error": Indicates a bug within the compiler. - */ - "level": "warning", - /* An array of source code locations to point out specific details about - where the diagnostic originates from. This may be empty, for example - for some global messages, or child messages attached to a parent. - - Character offsets are offsets of Unicode Scalar Values. - */ - "spans": [ - { - /* The file where the span is located. - For spans located within a macro expansion, this will be the - name of the expanded macro in the format "". - */ - "file_name": "lib.rs", - /* The byte offset where the span starts (0-based, inclusive). */ - "byte_start": 21, - /* The byte offset where the span ends (0-based, exclusive). */ - "byte_end": 22, - /* The first line number of the span (1-based, inclusive). */ - "line_start": 2, - /* The last line number of the span (1-based, inclusive). */ - "line_end": 2, - /* The first character offset of the line_start (1-based, inclusive). */ - "column_start": 9, - /* The last character offset of the line_end (1-based, exclusive). */ - "column_end": 10, - /* Whether or not this is the "primary" span. - - This indicates that this span is the focal point of the - diagnostic. - - There are rare cases where multiple spans may be marked as - primary. For example, "immutable borrow occurs here" and - "mutable borrow ends here" can be two separate primary spans. - - The top (parent) message should always have at least one - primary span, unless it has zero spans. Child messages may have - zero or more primary spans. - */ - "is_primary": true, - /* An array of objects showing the original source code for this - span. This shows the entire lines of text where the span is - located. A span across multiple lines will have a separate - value for each line. - */ - "text": [ - { - /* The entire line of the original source code. */ - "text": " let x = 123;", - /* The first character offset of the line of - where the span covers this line (1-based, inclusive). */ - "highlight_start": 9, - /* The last character offset of the line of - where the span covers this line (1-based, exclusive). */ - "highlight_end": 10 - } - ], - /* An optional message to display at this span location. - This is typically null for primary spans. - */ - "label": null, - /* An optional string of a suggested replacement for this span to - solve the issue. Tools may try to replace the contents of the - span with this text. - */ - "suggested_replacement": null, - /* An optional string that indicates the confidence of the - "suggested_replacement". Tools may use this value to determine - whether or not suggestions should be automatically applied. - - Possible values may be: - - "MachineApplicable": The suggestion is definitely what the - user intended. This suggestion should be automatically - applied. - - "MaybeIncorrect": The suggestion may be what the user - intended, but it is uncertain. The suggestion should result - in valid Rust code if it is applied. - - "HasPlaceholders": The suggestion contains placeholders like - `(...)`. The suggestion cannot be applied automatically - because it will not result in valid Rust code. The user will - need to fill in the placeholders. - - "Unspecified": The applicability of the suggestion is unknown. - */ - "suggestion_applicability": null, - /* An optional object indicating the expansion of a macro within - this span. - - If a message occurs within a macro invocation, this object will - provide details of where within the macro expansion the message - is located. - */ - "expansion": { - /* The span of the macro invocation. - Uses the same span definition as the "spans" array. - */ - "span": {/*...*/} - /* Name of the macro, such as "foo!" or "#[derive(Eq)]". */ - "macro_decl_name": "some_macro!", - /* Optional span where the relevant part of the macro is - defined. */ - "def_site_span": {/*...*/}, - } - } - ], - /* Array of attached diagnostic messages. - This is an array of objects using the same format as the parent - message. Children are not nested (children do not themselves - contain "children" definitions). - */ - "children": [ - { - "message": "`#[warn(unused_variables)]` on by default", - "code": null, - "level": "note", - "spans": [], - "children": [], - "rendered": null - }, - { - "message": "consider prefixing with an underscore", - "code": null, - "level": "help", - "spans": [ - { - "file_name": "lib.rs", - "byte_start": 21, - "byte_end": 22, - "line_start": 2, - "line_end": 2, - "column_start": 9, - "column_end": 10, - "is_primary": true, - "text": [ - { - "text": " let x = 123;", - "highlight_start": 9, - "highlight_end": 10 - } - ], - "label": null, - "suggested_replacement": "_x", - "suggestion_applicability": "MachineApplicable", - "expansion": null - } - ], - "children": [], - "rendered": null - } - ], - /* Optional string of the rendered version of the diagnostic as displayed - by rustc. Note that this may be influenced by the `--json` flag. - */ - "rendered": "warning: unused variable: `x`\n --> lib.rs:2:9\n |\n2 | let x = 123;\n | ^ help: consider prefixing with an underscore: `_x`\n |\n = note: `#[warn(unused_variables)]` on by default\n\n" -} -``` - -## Artifact notifications - -Artifact notifications are emitted when the [`--json=artifacts` -flag][option-json] is used. They indicate that a file artifact has been saved -to disk. More information about emit kinds may be found in the [`--emit` -flag][option-emit] documentation. - -```javascript -{ - /* The filename that was generated. */ - "artifact": "libfoo.rlib", - /* The kind of artifact that was generated. Possible values: - - "link": The generated crate as specified by the crate-type. - - "dep-info": The `.d` file with dependency information in a Makefile-like syntax. - - "metadata": The Rust `.rmeta` file containing metadata about the crate. - - "save-analysis": A JSON file emitted by the `-Zsave-analysis` feature. - */ - "emit": "link" -} -``` - -[option-emit]: command-line-arguments.md#option-emit -[option-error-format]: command-line-arguments.md#option-error-format -[option-json]: command-line-arguments.md#option-json diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md index 5688e90ada129..6574267f18511 100644 --- a/src/doc/rustc/src/lints/listing/deny-by-default.md +++ b/src/doc/rustc/src/lints/listing/deny-by-default.md @@ -222,28 +222,3 @@ error: invalid `crate_type` value | ^^^^^^^^^^^^^^^^^^^^ | ``` - -## const-err - -This lint detects expressions that will always panic at runtime and would be an -error in a `const` context. - -```rust,ignore -let _ = [0; 4][4]; -``` - -This will produce: - -```text -error: index out of bounds: the len is 4 but the index is 4 - --> src/lib.rs:1:9 - | -1 | let _ = [0; 4][4]; - | ^^^^^^^^^ - | -``` - -## order-dependent-trait-objects - -This lint detects a trait coherency violation that would allow creating two -trait impls for the same dynamic trait object involving marker traits. diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md index 813d7c4bafef8..e486240fda896 100644 --- a/src/doc/rustc/src/lints/listing/warn-by-default.md +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -596,6 +596,30 @@ warning: function cannot return without recursing | ``` +## unions-with-drop-fields + +This lint detects use of unions that contain fields with possibly non-trivial drop code. Some +example code that triggers this lint: + +```rust +#![feature(untagged_unions)] + +union U { + s: String, +} +``` + +This will produce: + +```text +warning: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union + --> src/main.rs:4:5 + | +4 | s: String, + | ^^^^^^^^^ + | +``` + ## unknown-lints This lint detects unrecognized lint attribute. Some diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md index d066f4a9cf59c..38be07a6440da 100644 --- a/src/doc/rustc/src/profile-guided-optimization.md +++ b/src/doc/rustc/src/profile-guided-optimization.md @@ -125,17 +125,6 @@ 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/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md index 5859df83f645b..3d63d072befe0 100644 --- a/src/doc/rustc/src/targets/index.md +++ b/src/doc/rustc/src/targets/index.md @@ -11,9 +11,3 @@ To compile to a particular target, use the `--target` flag: ```bash $ rustc src/main.rs --target=wasm32-unknown-unknown ``` -## Target Features -`x86`, and `ARMv8` are two popular CPU architectures. Their instruction sets form a common baseline across most CPUs. However, some CPUs extend these with custom instruction sets, e.g. vector (`AVX`), bitwise manipulation (`BMI`) or cryptographic (`AES`). - -Developers, who know on which CPUs their compiled code is going to run can choose to add (or remove) CPU specific instruction sets via the `-C target-feature=val` flag. - -Please note, that this flag is generally considered as unsafe. More details can be found in [this section](known-issues.md). diff --git a/src/doc/rustc/src/targets/known-issues.md b/src/doc/rustc/src/targets/known-issues.md deleted file mode 100644 index 89fd8ea6d32e9..0000000000000 --- a/src/doc/rustc/src/targets/known-issues.md +++ /dev/null @@ -1,13 +0,0 @@ -# Known Issues -This section informs you about known "gotchas". Keep in mind, that this section is (and always will be) incomplete. For suggestions and amendments, feel free to [contribute](../contributing.md) to this guide. - -## Target Features -Most target-feature problems arise, when mixing code that have the target-feature _enabled_ with code that have it _disabled_. If you want to avoid undefined behavior, it is recommended to build _all code_ (including the standard library and imported crates) with a common set of target-features. - -By default, compiling your code with the `-C target-feature` flag will not recompile the entire standard library and/or imported crates with matching target features. Therefore, target features are generally considered as unsafe. Using `#[target_feature]` on individual functions makes the function unsafe. - -Examples: - -| Target-Feature | Issue | Seen on | Description | Details | -| -------------- | ----- | ------- | ----------- | ------- | -| `+soft-float`
and
`-sse` | Segfaults and ABI mismatches | `x86` and `x86-64` | The `x86` and `x86_64` architecture uses SSE registers (aka `xmm`) for floating point operations. Using software emulated floats ("soft-floats") disables usage of `xmm` registers, but parts of Rust's core libraries (e.g. `std::f32` or `std::f64`) are compiled without soft-floats and expect parameters to be passed in `xmm` registers. This leads to ABI mismatches.

Attempting to compile with disabled SSE causes the same error, too. | [#63466](https://github.com/rust-lang/rust/issues/63466) | diff --git a/src/doc/unstable-book/src/compiler-flags/report-time.md b/src/doc/unstable-book/src/compiler-flags/report-time.md deleted file mode 100644 index ed4e9c6b56842..0000000000000 --- a/src/doc/unstable-book/src/compiler-flags/report-time.md +++ /dev/null @@ -1,80 +0,0 @@ -# `report-time` - -The tracking issue for this feature is: [#64888] - -[#64888]: https://github.com/rust-lang/rust/issues/64888 - ------------------------- - -The `report-time` feature adds a possibility to report execution time of the -tests generated via `libtest`. - -This is unstable feature, so you have to provide `-Zunstable-options` to get -this feature working. - -Sample usage command: - -```sh -./test_executable -Zunstable-options --report-time -``` - -Available options: - -```sh ---report-time [plain|colored] - Show execution time of each test. Awailable values: - plain = do not colorize the execution time (default); - colored = colorize output according to the `color` - parameter value; - Threshold values for colorized output can be - configured via - `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` - and - `RUST_TEST_TIME_DOCTEST` environment variables. - Expected format of environment variable is - `VARIABLE=WARN_TIME,CRITICAL_TIME`. - Not available for --format=terse ---ensure-time - Treat excess of the test execution time limit as - error. - Threshold values for this option can be configured via - `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` - and - `RUST_TEST_TIME_DOCTEST` environment variables. - Expected format of environment variable is - `VARIABLE=WARN_TIME,CRITICAL_TIME`. - `CRITICAL_TIME` here means the limit that should not be - exceeded by test. -``` - -Example of the environment variable format: - -```sh -RUST_TEST_TIME_UNIT=100,200 -``` - -where 100 stands for warn time, and 200 stands for critical time. - -## Examples - -```sh -cargo test --tests -- -Zunstable-options --report-time - Finished dev [unoptimized + debuginfo] target(s) in 0.02s - Running target/debug/deps/example-27fb188025bec02c - -running 3 tests -test tests::unit_test_quick ... ok <0.000s> -test tests::unit_test_warn ... ok <0.055s> -test tests::unit_test_critical ... ok <0.110s> - -test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out - - Running target/debug/deps/tests-cedb06f6526d15d9 - -running 3 tests -test unit_test_quick ... ok <0.000s> -test unit_test_warn ... ok <0.550s> -test unit_test_critical ... ok <1.100s> - -test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out -``` diff --git a/src/doc/unstable-book/src/language-features/non-exhaustive.md b/src/doc/unstable-book/src/language-features/non-exhaustive.md new file mode 100644 index 0000000000000..907147c17ef8e --- /dev/null +++ b/src/doc/unstable-book/src/language-features/non-exhaustive.md @@ -0,0 +1,76 @@ +# `non_exhaustive` + +The tracking issue for this feature is: [#44109] + +[#44109]: https://github.com/rust-lang/rust/issues/44109 + +------------------------ + +The `non_exhaustive` gate allows you to use the `#[non_exhaustive]` attribute +on structs, enums and enum variants. When applied within a crate, users of the +crate will need to use the `_` pattern when matching enums and use the `..` +pattern when matching structs. Enum variants cannot be matched against. +Structs and enum variants marked as `non_exhaustive` will not be able to +be created normally outside of the defining crate. This is demonstrated +below: + +```rust,ignore (pseudo-Rust) +use std::error::Error as StdError; + +#[non_exhaustive] +pub enum Error { + Message(String), + Other, +} +impl StdError for Error { + fn description(&self) -> &str { + // This will not error, despite being marked as non_exhaustive, as this + // enum is defined within the current crate, it can be matched + // exhaustively. + match *self { + Message(ref s) => s, + Other => "other or unknown error", + } + } +} +``` + +```rust,ignore (pseudo-Rust) +use mycrate::Error; + +// This will not error as the non_exhaustive Error enum has been matched with +// a wildcard. +match error { + Message(ref s) => ..., + Other => ..., + _ => ..., +} +``` + +```rust,ignore (pseudo-Rust) +#[non_exhaustive] +pub struct Config { + pub window_width: u16, + pub window_height: u16, +} + +// We can create structs as normal within the defining crate when marked as +// non_exhaustive. +let config = Config { window_width: 640, window_height: 480 }; + +// We can match structs exhaustively when within the defining crate. +if let Ok(Config { window_width, window_height }) = load_config() { + // ... +} +``` + +```rust,ignore (pseudo-Rust) +use mycrate::Config; + +// We cannot create a struct like normal if it has been marked as +// non_exhaustive. +let config = Config { window_width: 640, window_height: 480 }; +// By adding the `..` we can match the config as below outside of the crate +// when marked non_exhaustive. +let &Config { window_width, window_height, .. } = config; +``` diff --git a/src/doc/unstable-book/src/language-features/track-caller.md b/src/doc/unstable-book/src/language-features/track-caller.md deleted file mode 100644 index afc11a2b9492c..0000000000000 --- a/src/doc/unstable-book/src/language-features/track-caller.md +++ /dev/null @@ -1,5 +0,0 @@ -# `track_caller` - -The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809). - ------------------------- diff --git a/src/grammar/.gitignore b/src/grammar/.gitignore new file mode 100644 index 0000000000000..3e4498759434f --- /dev/null +++ b/src/grammar/.gitignore @@ -0,0 +1,3 @@ +*.class +*.java +*.tokens diff --git a/src/grammar/lexer.l b/src/grammar/lexer.l new file mode 100644 index 0000000000000..1feb781b2b39f --- /dev/null +++ b/src/grammar/lexer.l @@ -0,0 +1,350 @@ +%{ +#include +#include + +static int num_hashes; +static int end_hashes; +static int saw_non_hash; + +%} + +%option stack +%option yylineno + +%x str +%x rawstr +%x rawstr_esc_begin +%x rawstr_esc_body +%x rawstr_esc_end +%x byte +%x bytestr +%x rawbytestr +%x rawbytestr_nohash +%x pound +%x shebang_or_attr +%x ltorchar +%x linecomment +%x doc_line +%x blockcomment +%x doc_block +%x suffix + +ident [a-zA-Z\x80-\xff_][a-zA-Z0-9\x80-\xff_]* + +%% + +{ident} { BEGIN(INITIAL); } +(.|\n) { yyless(0); BEGIN(INITIAL); } + +[ \n\t\r] { } + +\xef\xbb\xbf { + // UTF-8 byte order mark (BOM), ignore if in line 1, error otherwise + if (yyget_lineno() != 1) { + return -1; + } +} + +\/\/(\/|\!) { BEGIN(doc_line); yymore(); } +\n { BEGIN(INITIAL); + yyleng--; + yytext[yyleng] = 0; + return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT); + } +[^\n]* { yymore(); } + +\/\/|\/\/\/\/ { BEGIN(linecomment); } +\n { BEGIN(INITIAL); } +[^\n]* { } + +\/\*(\*|\!)[^*] { yy_push_state(INITIAL); yy_push_state(doc_block); yymore(); } +\/\* { yy_push_state(doc_block); yymore(); } +\*\/ { + yy_pop_state(); + if (yy_top_state() == doc_block) { + yymore(); + } else { + return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT); + } +} +(.|\n) { yymore(); } + +\/\* { yy_push_state(blockcomment); } +\/\* { yy_push_state(blockcomment); } +\*\/ { yy_pop_state(); } +(.|\n) { } + +_ { return UNDERSCORE; } +abstract { return ABSTRACT; } +alignof { return ALIGNOF; } +as { return AS; } +become { return BECOME; } +box { return BOX; } +break { return BREAK; } +catch { return CATCH; } +const { return CONST; } +continue { return CONTINUE; } +crate { return CRATE; } +default { return DEFAULT; } +do { return DO; } +else { return ELSE; } +enum { return ENUM; } +extern { return EXTERN; } +false { return FALSE; } +final { return FINAL; } +fn { return FN; } +for { return FOR; } +if { return IF; } +impl { return IMPL; } +in { return IN; } +let { return LET; } +loop { return LOOP; } +macro { return MACRO; } +match { return MATCH; } +mod { return MOD; } +move { return MOVE; } +mut { return MUT; } +offsetof { return OFFSETOF; } +override { return OVERRIDE; } +priv { return PRIV; } +proc { return PROC; } +pure { return PURE; } +pub { return PUB; } +ref { return REF; } +return { return RETURN; } +self { return SELF; } +sizeof { return SIZEOF; } +static { return STATIC; } +struct { return STRUCT; } +super { return SUPER; } +trait { return TRAIT; } +true { return TRUE; } +type { return TYPE; } +typeof { return TYPEOF; } +union { return UNION; } +unsafe { return UNSAFE; } +unsized { return UNSIZED; } +use { return USE; } +virtual { return VIRTUAL; } +where { return WHERE; } +while { return WHILE; } +yield { return YIELD; } + +{ident} { return IDENT; } + +0x[0-9a-fA-F_]+ { BEGIN(suffix); return LIT_INTEGER; } +0o[0-7_]+ { BEGIN(suffix); return LIT_INTEGER; } +0b[01_]+ { BEGIN(suffix); return LIT_INTEGER; } +[0-9][0-9_]* { BEGIN(suffix); return LIT_INTEGER; } +[0-9][0-9_]*\.(\.|[a-zA-Z]) { yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; } + +[0-9][0-9_]*\.[0-9_]*([eE][-\+]?[0-9_]+)? { BEGIN(suffix); return LIT_FLOAT; } +[0-9][0-9_]*(\.[0-9_]*)?[eE][-\+]?[0-9_]+ { BEGIN(suffix); return LIT_FLOAT; } + +; { return ';'; } +, { return ','; } +\.\.\. { return DOTDOTDOT; } +\.\. { return DOTDOT; } +\. { return '.'; } +\( { return '('; } +\) { return ')'; } +\{ { return '{'; } +\} { return '}'; } +\[ { return '['; } +\] { return ']'; } +@ { return '@'; } +# { BEGIN(pound); yymore(); } +\! { BEGIN(shebang_or_attr); yymore(); } +\[ { + BEGIN(INITIAL); + yyless(2); + return SHEBANG; +} +[^\[\n]*\n { + // Since the \n was eaten as part of the token, yylineno will have + // been incremented to the value 2 if the shebang was on the first + // line. This yyless undoes that, setting yylineno back to 1. + yyless(yyleng - 1); + if (yyget_lineno() == 1) { + BEGIN(INITIAL); + return SHEBANG_LINE; + } else { + BEGIN(INITIAL); + yyless(2); + return SHEBANG; + } +} +. { BEGIN(INITIAL); yyless(1); return '#'; } + +\~ { return '~'; } +:: { return MOD_SEP; } +: { return ':'; } +\$ { return '$'; } +\? { return '?'; } + +== { return EQEQ; } +=> { return FAT_ARROW; } += { return '='; } +\!= { return NE; } +\! { return '!'; } +\<= { return LE; } +\<\< { return SHL; } +\<\<= { return SHLEQ; } +\< { return '<'; } +\>= { return GE; } +\>\> { return SHR; } +\>\>= { return SHREQ; } +\> { return '>'; } + +\x27 { BEGIN(ltorchar); yymore(); } +static { BEGIN(INITIAL); return STATIC_LIFETIME; } +{ident} { BEGIN(INITIAL); return LIFETIME; } +\\[nrt\\\x27\x220]\x27 { BEGIN(suffix); return LIT_CHAR; } +\\x[0-9a-fA-F]{2}\x27 { BEGIN(suffix); return LIT_CHAR; } +\\u\{([0-9a-fA-F]_*){1,6}\}\x27 { BEGIN(suffix); return LIT_CHAR; } +.\x27 { BEGIN(suffix); return LIT_CHAR; } +[\x80-\xff]{2,4}\x27 { BEGIN(suffix); return LIT_CHAR; } +<> { BEGIN(INITIAL); return -1; } + +b\x22 { BEGIN(bytestr); yymore(); } +\x22 { BEGIN(suffix); return LIT_BYTE_STR; } + +<> { return -1; } +\\[n\nrt\\\x27\x220] { yymore(); } +\\x[0-9a-fA-F]{2} { yymore(); } +\\u\{([0-9a-fA-F]_*){1,6}\} { yymore(); } +\\[^n\nrt\\\x27\x220] { return -1; } +(.|\n) { yymore(); } + +br\x22 { BEGIN(rawbytestr_nohash); yymore(); } +\x22 { BEGIN(suffix); return LIT_BYTE_STR_RAW; } +(.|\n) { yymore(); } +<> { return -1; } + +br/# { + BEGIN(rawbytestr); + yymore(); + num_hashes = 0; + saw_non_hash = 0; + end_hashes = 0; +} +# { + if (!saw_non_hash) { + num_hashes++; + } else if (end_hashes != 0) { + end_hashes++; + if (end_hashes == num_hashes) { + BEGIN(INITIAL); + return LIT_BYTE_STR_RAW; + } + } + yymore(); +} +\x22# { + end_hashes = 1; + if (end_hashes == num_hashes) { + BEGIN(INITIAL); + return LIT_BYTE_STR_RAW; + } + yymore(); +} +(.|\n) { + if (!saw_non_hash) { + saw_non_hash = 1; + } + if (end_hashes != 0) { + end_hashes = 0; + } + yymore(); +} +<> { return -1; } + +b\x27 { BEGIN(byte); yymore(); } +\\[nrt\\\x27\x220]\x27 { BEGIN(INITIAL); return LIT_BYTE; } +\\x[0-9a-fA-F]{2}\x27 { BEGIN(INITIAL); return LIT_BYTE; } +\\u([0-9a-fA-F]_*){4}\x27 { BEGIN(INITIAL); return LIT_BYTE; } +\\U([0-9a-fA-F]_*){8}\x27 { BEGIN(INITIAL); return LIT_BYTE; } +.\x27 { BEGIN(INITIAL); return LIT_BYTE; } +<> { BEGIN(INITIAL); return -1; } + +r\x22 { BEGIN(rawstr); yymore(); } +\x22 { BEGIN(suffix); return LIT_STR_RAW; } +(.|\n) { yymore(); } +<> { return -1; } + +r/# { + BEGIN(rawstr_esc_begin); + yymore(); + num_hashes = 0; + saw_non_hash = 0; + end_hashes = 0; +} + +# { + num_hashes++; + yymore(); +} +\x22 { + BEGIN(rawstr_esc_body); + yymore(); +} +(.|\n) { return -1; } + +\x22/# { + BEGIN(rawstr_esc_end); + yymore(); + } +(.|\n) { + yymore(); + } + +# { + end_hashes++; + if (end_hashes == num_hashes) { + BEGIN(INITIAL); + return LIT_STR_RAW; + } + yymore(); + } +[^#] { + end_hashes = 0; + BEGIN(rawstr_esc_body); + yymore(); + } + +<> { return -1; } + +\x22 { BEGIN(str); yymore(); } +\x22 { BEGIN(suffix); return LIT_STR; } + +<> { return -1; } +\\[n\nr\rt\\\x27\x220] { yymore(); } +\\x[0-9a-fA-F]{2} { yymore(); } +\\u\{([0-9a-fA-F]_*){1,6}\} { yymore(); } +\\[^n\nrt\\\x27\x220] { return -1; } +(.|\n) { yymore(); } + +\<- { return LARROW; } +-\> { return RARROW; } +- { return '-'; } +-= { return MINUSEQ; } +&& { return ANDAND; } +& { return '&'; } +&= { return ANDEQ; } +\|\| { return OROR; } +\| { return '|'; } +\|= { return OREQ; } +\+ { return '+'; } +\+= { return PLUSEQ; } +\* { return '*'; } +\*= { return STAREQ; } +\/ { return '/'; } +\/= { return SLASHEQ; } +\^ { return '^'; } +\^= { return CARETEQ; } +% { return '%'; } +%= { return PERCENTEQ; } + +<> { return 0; } + +%% diff --git a/src/grammar/parser-lalr-main.c b/src/grammar/parser-lalr-main.c new file mode 100644 index 0000000000000..6348190cc140b --- /dev/null +++ b/src/grammar/parser-lalr-main.c @@ -0,0 +1,193 @@ +#include +#include +#include +#include + +extern int yylex(); +extern int rsparse(); + +#define PUSHBACK_LEN 4 + +static char pushback[PUSHBACK_LEN]; +static int verbose; + +void print(const char* format, ...) { + va_list args; + va_start(args, format); + if (verbose) { + vprintf(format, args); + } + va_end(args); +} + +// If there is a non-null char at the head of the pushback queue, +// dequeue it and shift the rest of the queue forwards. Otherwise, +// return the token from calling yylex. +int rslex() { + if (pushback[0] == '\0') { + return yylex(); + } else { + char c = pushback[0]; + memmove(pushback, pushback + 1, PUSHBACK_LEN - 1); + pushback[PUSHBACK_LEN - 1] = '\0'; + return c; + } +} + +// Note: this does nothing if the pushback queue is full. As long as +// there aren't more than PUSHBACK_LEN consecutive calls to push_back +// in an action, this shouldn't be a problem. +void push_back(char c) { + for (int i = 0; i < PUSHBACK_LEN; ++i) { + if (pushback[i] == '\0') { + pushback[i] = c; + break; + } + } +} + +extern int rsdebug; + +struct node { + struct node *next; + struct node *prev; + int own_string; + char const *name; + int n_elems; + struct node *elems[]; +}; + +struct node *nodes = NULL; +int n_nodes; + +struct node *mk_node(char const *name, int n, ...) { + va_list ap; + int i = 0; + unsigned sz = sizeof(struct node) + (n * sizeof(struct node *)); + struct node *nn, *nd = (struct node *)malloc(sz); + + print("# New %d-ary node: %s = %p\n", n, name, nd); + + nd->own_string = 0; + nd->prev = NULL; + nd->next = nodes; + if (nodes) { + nodes->prev = nd; + } + nodes = nd; + + nd->name = name; + nd->n_elems = n; + + va_start(ap, n); + while (i < n) { + nn = va_arg(ap, struct node *); + print("# arg[%d]: %p\n", i, nn); + print("# (%s ...)\n", nn->name); + nd->elems[i++] = nn; + } + va_end(ap); + n_nodes++; + return nd; +} + +struct node *mk_atom(char *name) { + struct node *nd = mk_node((char const *)strdup(name), 0); + nd->own_string = 1; + return nd; +} + +struct node *mk_none() { + return mk_atom(""); +} + +struct node *ext_node(struct node *nd, int n, ...) { + va_list ap; + int i = 0, c = nd->n_elems + n; + unsigned sz = sizeof(struct node) + (c * sizeof(struct node *)); + struct node *nn; + + print("# Extending %d-ary node by %d nodes: %s = %p", + nd->n_elems, c, nd->name, nd); + + if (nd->next) { + nd->next->prev = nd->prev; + } + if (nd->prev) { + nd->prev->next = nd->next; + } + nd = realloc(nd, sz); + nd->prev = NULL; + nd->next = nodes; + nodes->prev = nd; + nodes = nd; + + print(" ==> %p\n", nd); + + va_start(ap, n); + while (i < n) { + nn = va_arg(ap, struct node *); + print("# arg[%d]: %p\n", i, nn); + print("# (%s ...)\n", nn->name); + nd->elems[nd->n_elems++] = nn; + ++i; + } + va_end(ap); + return nd; +} + +int const indent_step = 4; + +void print_indent(int depth) { + while (depth) { + if (depth-- % indent_step == 0) { + print("|"); + } else { + print(" "); + } + } +} + +void print_node(struct node *n, int depth) { + int i = 0; + print_indent(depth); + if (n->n_elems == 0) { + print("%s\n", n->name); + } else { + print("(%s\n", n->name); + for (i = 0; i < n->n_elems; ++i) { + print_node(n->elems[i], depth + indent_step); + } + print_indent(depth); + print(")\n"); + } +} + +int main(int argc, char **argv) { + if (argc == 2 && strcmp(argv[1], "-v") == 0) { + verbose = 1; + } else { + verbose = 0; + } + int ret = 0; + struct node *tmp; + memset(pushback, '\0', PUSHBACK_LEN); + ret = rsparse(); + print("--- PARSE COMPLETE: ret:%d, n_nodes:%d ---\n", ret, n_nodes); + if (nodes) { + print_node(nodes, 0); + } + while (nodes) { + tmp = nodes; + nodes = tmp->next; + if (tmp->own_string) { + free((void*)tmp->name); + } + free(tmp); + } + return ret; +} + +void rserror(char const *s) { + fprintf(stderr, "%s\n", s); +} diff --git a/src/grammar/parser-lalr.y b/src/grammar/parser-lalr.y new file mode 100644 index 0000000000000..5585c95a5a63a --- /dev/null +++ b/src/grammar/parser-lalr.y @@ -0,0 +1,1982 @@ +%{ +#define YYERROR_VERBOSE +#define YYSTYPE struct node * +struct node; +extern int yylex(); +extern void yyerror(char const *s); +extern struct node *mk_node(char const *name, int n, ...); +extern struct node *mk_atom(char *text); +extern struct node *mk_none(); +extern struct node *ext_node(struct node *nd, int n, ...); +extern void push_back(char c); +extern char *yytext; +%} +%debug + +%token SHL +%token SHR +%token LE +%token EQEQ +%token NE +%token GE +%token ANDAND +%token OROR +%token SHLEQ +%token SHREQ +%token MINUSEQ +%token ANDEQ +%token OREQ +%token PLUSEQ +%token STAREQ +%token SLASHEQ +%token CARETEQ +%token PERCENTEQ +%token DOTDOT +%token DOTDOTDOT +%token MOD_SEP +%token RARROW +%token LARROW +%token FAT_ARROW +%token LIT_BYTE +%token LIT_CHAR +%token LIT_INTEGER +%token LIT_FLOAT +%token LIT_STR +%token LIT_STR_RAW +%token LIT_BYTE_STR +%token LIT_BYTE_STR_RAW +%token IDENT +%token UNDERSCORE +%token LIFETIME + +// keywords +%token SELF +%token STATIC +%token ABSTRACT +%token ALIGNOF +%token AS +%token BECOME +%token BREAK +%token CATCH +%token CRATE +%token DO +%token ELSE +%token ENUM +%token EXTERN +%token FALSE +%token FINAL +%token FN +%token FOR +%token IF +%token IMPL +%token IN +%token LET +%token LOOP +%token MACRO +%token MATCH +%token MOD +%token MOVE +%token MUT +%token OFFSETOF +%token OVERRIDE +%token PRIV +%token PUB +%token PURE +%token REF +%token RETURN +%token SIZEOF +%token STRUCT +%token SUPER +%token UNION +%token UNSIZED +%token TRUE +%token TRAIT +%token TYPE +%token UNSAFE +%token VIRTUAL +%token YIELD +%token DEFAULT +%token USE +%token WHILE +%token CONTINUE +%token PROC +%token BOX +%token CONST +%token WHERE +%token TYPEOF +%token INNER_DOC_COMMENT +%token OUTER_DOC_COMMENT + +%token SHEBANG +%token SHEBANG_LINE +%token STATIC_LIFETIME + + /* + Quoting from the Bison manual: + + "Finally, the resolution of conflicts works by comparing the precedence + of the rule being considered with that of the lookahead token. If the + token's precedence is higher, the choice is to shift. If the rule's + precedence is higher, the choice is to reduce. If they have equal + precedence, the choice is made based on the associativity of that + precedence level. The verbose output file made by ‘-v’ (see Invoking + Bison) says how each conflict was resolved" + */ + +// We expect no shift/reduce or reduce/reduce conflicts in this grammar; +// all potential ambiguities are scrutinized and eliminated manually. +%expect 0 + +// fake-precedence symbol to cause '|' bars in lambda context to parse +// at low precedence, permit things like |x| foo = bar, where '=' is +// otherwise lower-precedence than '|'. Also used for proc() to cause +// things like proc() a + b to parse as proc() { a + b }. +%precedence LAMBDA + +%precedence SELF + +// MUT should be lower precedence than IDENT so that in the pat rule, +// "& MUT pat" has higher precedence than "binding_mode ident [@ pat]" +%precedence MUT + +// IDENT needs to be lower than '{' so that 'foo {' is shifted when +// trying to decide if we've got a struct-construction expr (esp. in +// contexts like 'if foo { .') +// +// IDENT also needs to be lower precedence than '<' so that '<' in +// 'foo:bar . <' is shifted (in a trait reference occurring in a +// bounds list), parsing as foo:(bar) rather than (foo:bar). +%precedence IDENT + // Put the weak keywords that can be used as idents here as well +%precedence CATCH +%precedence DEFAULT +%precedence UNION + +// A couple fake-precedence symbols to use in rules associated with + +// and < in trailing type contexts. These come up when you have a type +// in the RHS of operator-AS, such as "foo as bar". The "<" there +// has to be shifted so the parser keeps trying to parse a type, even +// though it might well consider reducing the type "bar" and then +// going on to "<" as a subsequent binop. The "+" case is with +// trailing type-bounds ("foo as bar:A+B"), for the same reason. +%precedence SHIFTPLUS + +%precedence MOD_SEP +%precedence RARROW ':' + +// In where clauses, "for" should have greater precedence when used as +// a higher ranked constraint than when used as the beginning of a +// for_in_type (which is a ty) +%precedence FORTYPE +%precedence FOR + +// Binops & unops, and their precedences +%precedence '?' +%precedence BOX +%nonassoc DOTDOT + +// RETURN needs to be lower-precedence than tokens that start +// prefix_exprs +%precedence RETURN YIELD + +%right '=' SHLEQ SHREQ MINUSEQ ANDEQ OREQ PLUSEQ STAREQ SLASHEQ CARETEQ PERCENTEQ +%right LARROW +%left OROR +%left ANDAND +%left EQEQ NE +%left '<' '>' LE GE +%left '|' +%left '^' +%left '&' +%left SHL SHR +%left '+' '-' +%precedence AS +%left '*' '/' '%' +%precedence '!' + +%precedence '{' '[' '(' '.' + +%precedence RANGE + +%start crate + +%% + +//////////////////////////////////////////////////////////////////////// +// Part 1: Items and attributes +//////////////////////////////////////////////////////////////////////// + +crate +: maybe_shebang inner_attrs maybe_mod_items { mk_node("crate", 2, $2, $3); } +| maybe_shebang maybe_mod_items { mk_node("crate", 1, $2); } +; + +maybe_shebang +: SHEBANG_LINE +| %empty +; + +maybe_inner_attrs +: inner_attrs +| %empty { $$ = mk_none(); } +; + +inner_attrs +: inner_attr { $$ = mk_node("InnerAttrs", 1, $1); } +| inner_attrs inner_attr { $$ = ext_node($1, 1, $2); } +; + +inner_attr +: SHEBANG '[' meta_item ']' { $$ = mk_node("InnerAttr", 1, $3); } +| INNER_DOC_COMMENT { $$ = mk_node("InnerAttr", 1, mk_node("doc-comment", 1, mk_atom(yytext))); } +; + +maybe_outer_attrs +: outer_attrs +| %empty { $$ = mk_none(); } +; + +outer_attrs +: outer_attr { $$ = mk_node("OuterAttrs", 1, $1); } +| outer_attrs outer_attr { $$ = ext_node($1, 1, $2); } +; + +outer_attr +: '#' '[' meta_item ']' { $$ = $3; } +| OUTER_DOC_COMMENT { $$ = mk_node("doc-comment", 1, mk_atom(yytext)); } +; + +meta_item +: ident { $$ = mk_node("MetaWord", 1, $1); } +| ident '=' lit { $$ = mk_node("MetaNameValue", 2, $1, $3); } +| ident '(' meta_seq ')' { $$ = mk_node("MetaList", 2, $1, $3); } +| ident '(' meta_seq ',' ')' { $$ = mk_node("MetaList", 2, $1, $3); } +; + +meta_seq +: %empty { $$ = mk_none(); } +| meta_item { $$ = mk_node("MetaItems", 1, $1); } +| meta_seq ',' meta_item { $$ = ext_node($1, 1, $3); } +; + +maybe_mod_items +: mod_items +| %empty { $$ = mk_none(); } +; + +mod_items +: mod_item { $$ = mk_node("Items", 1, $1); } +| mod_items mod_item { $$ = ext_node($1, 1, $2); } +; + +attrs_and_vis +: maybe_outer_attrs visibility { $$ = mk_node("AttrsAndVis", 2, $1, $2); } +; + +mod_item +: attrs_and_vis item { $$ = mk_node("Item", 2, $1, $2); } +; + +// items that can appear outside of a fn block +item +: stmt_item +| item_macro +; + +// items that can appear in "stmts" +stmt_item +: item_static +| item_const +| item_type +| block_item +| view_item +; + +item_static +: STATIC ident ':' ty '=' expr ';' { $$ = mk_node("ItemStatic", 3, $2, $4, $6); } +| STATIC MUT ident ':' ty '=' expr ';' { $$ = mk_node("ItemStatic", 3, $3, $5, $7); } +; + +item_const +: CONST ident ':' ty '=' expr ';' { $$ = mk_node("ItemConst", 3, $2, $4, $6); } +; + +item_macro +: path_expr '!' maybe_ident parens_delimited_token_trees ';' { $$ = mk_node("ItemMacro", 3, $1, $3, $4); } +| path_expr '!' maybe_ident braces_delimited_token_trees { $$ = mk_node("ItemMacro", 3, $1, $3, $4); } +| path_expr '!' maybe_ident brackets_delimited_token_trees ';'{ $$ = mk_node("ItemMacro", 3, $1, $3, $4); } +; + +view_item +: use_item +| extern_fn_item +| EXTERN CRATE ident ';' { $$ = mk_node("ViewItemExternCrate", 1, $3); } +| EXTERN CRATE ident AS ident ';' { $$ = mk_node("ViewItemExternCrate", 2, $3, $5); } +; + +extern_fn_item +: EXTERN maybe_abi item_fn { $$ = mk_node("ViewItemExternFn", 2, $2, $3); } +; + +use_item +: USE view_path ';' { $$ = mk_node("ViewItemUse", 1, $2); } +; + +view_path +: path_no_types_allowed { $$ = mk_node("ViewPathSimple", 1, $1); } +| path_no_types_allowed MOD_SEP '{' '}' { $$ = mk_node("ViewPathList", 2, $1, mk_atom("ViewPathListEmpty")); } +| MOD_SEP '{' '}' { $$ = mk_node("ViewPathList", 1, mk_atom("ViewPathListEmpty")); } +| path_no_types_allowed MOD_SEP '{' idents_or_self '}' { $$ = mk_node("ViewPathList", 2, $1, $4); } +| MOD_SEP '{' idents_or_self '}' { $$ = mk_node("ViewPathList", 1, $3); } +| path_no_types_allowed MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 2, $1, $4); } +| MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $3); } +| path_no_types_allowed MOD_SEP '*' { $$ = mk_node("ViewPathGlob", 1, $1); } +| MOD_SEP '*' { $$ = mk_atom("ViewPathGlob"); } +| '*' { $$ = mk_atom("ViewPathGlob"); } +| '{' '}' { $$ = mk_atom("ViewPathListEmpty"); } +| '{' idents_or_self '}' { $$ = mk_node("ViewPathList", 1, $2); } +| '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $2); } +| path_no_types_allowed AS ident { $$ = mk_node("ViewPathSimple", 2, $1, $3); } +; + +block_item +: item_fn +| item_unsafe_fn +| item_mod +| item_foreign_mod { $$ = mk_node("ItemForeignMod", 1, $1); } +| item_struct +| item_enum +| item_union +| item_trait +| item_impl +; + +maybe_ty_ascription +: ':' ty_sum { $$ = $2; } +| %empty { $$ = mk_none(); } +; + +maybe_init_expr +: '=' expr { $$ = $2; } +| %empty { $$ = mk_none(); } +; + +// structs +item_struct +: STRUCT ident generic_params maybe_where_clause struct_decl_args +{ + $$ = mk_node("ItemStruct", 4, $2, $3, $4, $5); +} +| STRUCT ident generic_params struct_tuple_args maybe_where_clause ';' +{ + $$ = mk_node("ItemStruct", 4, $2, $3, $4, $5); +} +| STRUCT ident generic_params maybe_where_clause ';' +{ + $$ = mk_node("ItemStruct", 3, $2, $3, $4); +} +; + +struct_decl_args +: '{' struct_decl_fields '}' { $$ = $2; } +| '{' struct_decl_fields ',' '}' { $$ = $2; } +; + +struct_tuple_args +: '(' struct_tuple_fields ')' { $$ = $2; } +| '(' struct_tuple_fields ',' ')' { $$ = $2; } +; + +struct_decl_fields +: struct_decl_field { $$ = mk_node("StructFields", 1, $1); } +| struct_decl_fields ',' struct_decl_field { $$ = ext_node($1, 1, $3); } +| %empty { $$ = mk_none(); } +; + +struct_decl_field +: attrs_and_vis ident ':' ty_sum { $$ = mk_node("StructField", 3, $1, $2, $4); } +; + +struct_tuple_fields +: struct_tuple_field { $$ = mk_node("StructFields", 1, $1); } +| struct_tuple_fields ',' struct_tuple_field { $$ = ext_node($1, 1, $3); } +| %empty { $$ = mk_none(); } +; + +struct_tuple_field +: attrs_and_vis ty_sum { $$ = mk_node("StructField", 2, $1, $2); } +; + +// enums +item_enum +: ENUM ident generic_params maybe_where_clause '{' enum_defs '}' { $$ = mk_node("ItemEnum", 0); } +| ENUM ident generic_params maybe_where_clause '{' enum_defs ',' '}' { $$ = mk_node("ItemEnum", 0); } +; + +enum_defs +: enum_def { $$ = mk_node("EnumDefs", 1, $1); } +| enum_defs ',' enum_def { $$ = ext_node($1, 1, $3); } +| %empty { $$ = mk_none(); } +; + +enum_def +: attrs_and_vis ident enum_args { $$ = mk_node("EnumDef", 3, $1, $2, $3); } +; + +enum_args +: '{' struct_decl_fields '}' { $$ = mk_node("EnumArgs", 1, $2); } +| '{' struct_decl_fields ',' '}' { $$ = mk_node("EnumArgs", 1, $2); } +| '(' maybe_ty_sums ')' { $$ = mk_node("EnumArgs", 1, $2); } +| '=' expr { $$ = mk_node("EnumArgs", 1, $2); } +| %empty { $$ = mk_none(); } +; + +// unions +item_union +: UNION ident generic_params maybe_where_clause '{' struct_decl_fields '}' { $$ = mk_node("ItemUnion", 0); } +| UNION ident generic_params maybe_where_clause '{' struct_decl_fields ',' '}' { $$ = mk_node("ItemUnion", 0); } + +item_mod +: MOD ident ';' { $$ = mk_node("ItemMod", 1, $2); } +| MOD ident '{' maybe_mod_items '}' { $$ = mk_node("ItemMod", 2, $2, $4); } +| MOD ident '{' inner_attrs maybe_mod_items '}' { $$ = mk_node("ItemMod", 3, $2, $4, $5); } +; + +item_foreign_mod +: EXTERN maybe_abi '{' maybe_foreign_items '}' { $$ = mk_node("ItemForeignMod", 1, $4); } +| EXTERN maybe_abi '{' inner_attrs maybe_foreign_items '}' { $$ = mk_node("ItemForeignMod", 2, $4, $5); } +; + +maybe_abi +: str +| %empty { $$ = mk_none(); } +; + +maybe_foreign_items +: foreign_items +| %empty { $$ = mk_none(); } +; + +foreign_items +: foreign_item { $$ = mk_node("ForeignItems", 1, $1); } +| foreign_items foreign_item { $$ = ext_node($1, 1, $2); } +; + +foreign_item +: attrs_and_vis STATIC item_foreign_static { $$ = mk_node("ForeignItem", 2, $1, $3); } +| attrs_and_vis item_foreign_fn { $$ = mk_node("ForeignItem", 2, $1, $2); } +| attrs_and_vis UNSAFE item_foreign_fn { $$ = mk_node("ForeignItem", 2, $1, $3); } +; + +item_foreign_static +: maybe_mut ident ':' ty ';' { $$ = mk_node("StaticItem", 3, $1, $2, $4); } +; + +item_foreign_fn +: FN ident generic_params fn_decl_allow_variadic maybe_where_clause ';' { $$ = mk_node("ForeignFn", 4, $2, $3, $4, $5); } +; + +fn_decl_allow_variadic +: fn_params_allow_variadic ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); } +; + +fn_params_allow_variadic +: '(' ')' { $$ = mk_none(); } +| '(' params ')' { $$ = $2; } +| '(' params ',' ')' { $$ = $2; } +| '(' params ',' DOTDOTDOT ')' { $$ = $2; } +; + +visibility +: PUB { $$ = mk_atom("Public"); } +| %empty { $$ = mk_atom("Inherited"); } +; + +idents_or_self +: ident_or_self { $$ = mk_node("IdentsOrSelf", 1, $1); } +| idents_or_self AS ident { $$ = mk_node("IdentsOrSelf", 2, $1, $3); } +| idents_or_self ',' ident_or_self { $$ = ext_node($1, 1, $3); } +; + +ident_or_self +: ident +| SELF { $$ = mk_atom(yytext); } +; + +item_type +: TYPE ident generic_params maybe_where_clause '=' ty_sum ';' { $$ = mk_node("ItemTy", 4, $2, $3, $4, $6); } +; + +for_sized +: FOR '?' ident { $$ = mk_node("ForSized", 1, $3); } +| FOR ident '?' { $$ = mk_node("ForSized", 1, $2); } +| %empty { $$ = mk_none(); } +; + +item_trait +: maybe_unsafe TRAIT ident generic_params for_sized maybe_ty_param_bounds maybe_where_clause '{' maybe_trait_items '}' +{ + $$ = mk_node("ItemTrait", 7, $1, $3, $4, $5, $6, $7, $9); +} +; + +maybe_trait_items +: trait_items +| %empty { $$ = mk_none(); } +; + +trait_items +: trait_item { $$ = mk_node("TraitItems", 1, $1); } +| trait_items trait_item { $$ = ext_node($1, 1, $2); } +; + +trait_item +: trait_const +| trait_type +| trait_method +| maybe_outer_attrs item_macro { $$ = mk_node("TraitMacroItem", 2, $1, $2); } +; + +trait_const +: maybe_outer_attrs CONST ident maybe_ty_ascription maybe_const_default ';' { $$ = mk_node("ConstTraitItem", 4, $1, $3, $4, $5); } +; + +maybe_const_default +: '=' expr { $$ = mk_node("ConstDefault", 1, $2); } +| %empty { $$ = mk_none(); } +; + +trait_type +: maybe_outer_attrs TYPE ty_param ';' { $$ = mk_node("TypeTraitItem", 2, $1, $3); } +; + +maybe_unsafe +: UNSAFE { $$ = mk_atom("Unsafe"); } +| %empty { $$ = mk_none(); } +; + +maybe_default_maybe_unsafe +: DEFAULT UNSAFE { $$ = mk_atom("DefaultUnsafe"); } +| DEFAULT { $$ = mk_atom("Default"); } +| UNSAFE { $$ = mk_atom("Unsafe"); } +| %empty { $$ = mk_none(); } + +trait_method +: type_method { $$ = mk_node("Required", 1, $1); } +| method { $$ = mk_node("Provided", 1, $1); } +; + +type_method +: maybe_outer_attrs maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' +{ + $$ = mk_node("TypeMethod", 6, $1, $2, $4, $5, $6, $7); +} +| maybe_outer_attrs CONST maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' +{ + $$ = mk_node("TypeMethod", 6, $1, $3, $5, $6, $7, $8); +} +| maybe_outer_attrs maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' +{ + $$ = mk_node("TypeMethod", 7, $1, $2, $4, $6, $7, $8, $9); +} +; + +method +: maybe_outer_attrs maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("Method", 7, $1, $2, $4, $5, $6, $7, $8); +} +| maybe_outer_attrs CONST maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("Method", 7, $1, $3, $5, $6, $7, $8, $9); +} +| maybe_outer_attrs maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10); +} +; + +impl_method +: attrs_and_vis maybe_default maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("Method", 8, $1, $2, $3, $5, $6, $7, $8, $9); +} +| attrs_and_vis maybe_default CONST maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10); +} +| attrs_and_vis maybe_default maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("Method", 9, $1, $2, $3, $5, $7, $8, $9, $10, $11); +} +; + +// There are two forms of impl: +// +// impl (<...>)? TY { ... } +// impl (<...>)? TRAIT for TY { ... } +// +// Unfortunately since TY can begin with '<' itself -- as part of a +// TyQualifiedPath type -- there's an s/r conflict when we see '<' after IMPL: +// should we reduce one of the early rules of TY (such as maybe_once) +// or shall we continue shifting into the generic_params list for the +// impl? +// +// The production parser disambiguates a different case here by +// permitting / requiring the user to provide parens around types when +// they are ambiguous with traits. We do the same here, regrettably, +// by splitting ty into ty and ty_prim. +item_impl +: maybe_default_maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' +{ + $$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8); +} +| maybe_default_maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' +{ + $$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10); +} +| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' +{ + $$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10); +} +| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' +{ + $$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11); +} +| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}' +{ + $$ = mk_node("ItemImplDefault", 3, $1, $3, $4); +} +| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}' +{ + $$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4); +} +; + +maybe_impl_items +: impl_items +| %empty { $$ = mk_none(); } +; + +impl_items +: impl_item { $$ = mk_node("ImplItems", 1, $1); } +| impl_item impl_items { $$ = ext_node($1, 1, $2); } +; + +impl_item +: impl_method +| attrs_and_vis item_macro { $$ = mk_node("ImplMacroItem", 2, $1, $2); } +| impl_const +| impl_type +; + +maybe_default +: DEFAULT { $$ = mk_atom("Default"); } +| %empty { $$ = mk_none(); } +; + +impl_const +: attrs_and_vis maybe_default item_const { $$ = mk_node("ImplConst", 3, $1, $2, $3); } +; + +impl_type +: attrs_and_vis maybe_default TYPE ident generic_params '=' ty_sum ';' { $$ = mk_node("ImplType", 5, $1, $2, $4, $5, $7); } +; + +item_fn +: FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("ItemFn", 5, $2, $3, $4, $5, $6); +} +| CONST FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("ItemFn", 5, $3, $4, $5, $6, $7); +} +; + +item_unsafe_fn +: UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("ItemUnsafeFn", 5, $3, $4, $5, $6, $7); +} +| CONST UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("ItemUnsafeFn", 5, $4, $5, $6, $7, $8); +} +| UNSAFE EXTERN maybe_abi FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("ItemUnsafeFn", 6, $3, $5, $6, $7, $8, $9); +} +; + +fn_decl +: fn_params ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); } +; + +fn_decl_with_self +: fn_params_with_self ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); } +; + +fn_decl_with_self_allow_anon_params +: fn_anon_params_with_self ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); } +; + +fn_params +: '(' maybe_params ')' { $$ = $2; } +; + +fn_anon_params +: '(' anon_param anon_params_allow_variadic_tail ')' { $$ = ext_node($2, 1, $3); } +| '(' ')' { $$ = mk_none(); } +; + +fn_params_with_self +: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfLower", 3, $2, $4, $5); } +| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfRegion", 3, $3, $5, $6); } +| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); } +| '(' maybe_params ')' { $$ = mk_node("SelfStatic", 1, $2); } +; + +fn_anon_params_with_self +: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfLower", 3, $2, $4, $5); } +| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfRegion", 3, $3, $5, $6); } +| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); } +| '(' maybe_anon_params ')' { $$ = mk_node("SelfStatic", 1, $2); } +; + +maybe_params +: params +| params ',' +| %empty { $$ = mk_none(); } +; + +params +: param { $$ = mk_node("Args", 1, $1); } +| params ',' param { $$ = ext_node($1, 1, $3); } +; + +param +: pat ':' ty_sum { $$ = mk_node("Arg", 2, $1, $3); } +; + +inferrable_params +: inferrable_param { $$ = mk_node("InferrableParams", 1, $1); } +| inferrable_params ',' inferrable_param { $$ = ext_node($1, 1, $3); } +; + +inferrable_param +: pat maybe_ty_ascription { $$ = mk_node("InferrableParam", 2, $1, $2); } +; + +maybe_comma_params +: ',' { $$ = mk_none(); } +| ',' params { $$ = $2; } +| ',' params ',' { $$ = $2; } +| %empty { $$ = mk_none(); } +; + +maybe_comma_anon_params +: ',' { $$ = mk_none(); } +| ',' anon_params { $$ = $2; } +| ',' anon_params ',' { $$ = $2; } +| %empty { $$ = mk_none(); } +; + +maybe_anon_params +: anon_params +| anon_params ',' +| %empty { $$ = mk_none(); } +; + +anon_params +: anon_param { $$ = mk_node("Args", 1, $1); } +| anon_params ',' anon_param { $$ = ext_node($1, 1, $3); } +; + +// anon means it's allowed to be anonymous (type-only), but it can +// still have a name +anon_param +: named_arg ':' ty { $$ = mk_node("Arg", 2, $1, $3); } +| ty +; + +anon_params_allow_variadic_tail +: ',' DOTDOTDOT { $$ = mk_none(); } +| ',' anon_param anon_params_allow_variadic_tail { $$ = mk_node("Args", 2, $2, $3); } +| %empty { $$ = mk_none(); } +; + +named_arg +: ident +| UNDERSCORE { $$ = mk_atom("PatWild"); } +| '&' ident { $$ = $2; } +| '&' UNDERSCORE { $$ = mk_atom("PatWild"); } +| ANDAND ident { $$ = $2; } +| ANDAND UNDERSCORE { $$ = mk_atom("PatWild"); } +| MUT ident { $$ = $2; } +; + +ret_ty +: RARROW '!' { $$ = mk_none(); } +| RARROW ty { $$ = mk_node("ret-ty", 1, $2); } +| %prec IDENT %empty { $$ = mk_none(); } +; + +generic_params +: '<' '>' { $$ = mk_node("Generics", 2, mk_none(), mk_none()); } +| '<' lifetimes '>' { $$ = mk_node("Generics", 2, $2, mk_none()); } +| '<' lifetimes ',' '>' { $$ = mk_node("Generics", 2, $2, mk_none()); } +| '<' lifetimes SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); } +| '<' lifetimes ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); } +| '<' lifetimes ',' ty_params '>' { $$ = mk_node("Generics", 2, $2, $4); } +| '<' lifetimes ',' ty_params ',' '>' { $$ = mk_node("Generics", 2, $2, $4); } +| '<' lifetimes ',' ty_params SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, $4); } +| '<' lifetimes ',' ty_params ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, $4); } +| '<' ty_params '>' { $$ = mk_node("Generics", 2, mk_none(), $2); } +| '<' ty_params ',' '>' { $$ = mk_node("Generics", 2, mk_none(), $2); } +| '<' ty_params SHR { push_back('>'); $$ = mk_node("Generics", 2, mk_none(), $2); } +| '<' ty_params ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, mk_none(), $2); } +| %empty { $$ = mk_none(); } +; + +maybe_where_clause +: %empty { $$ = mk_none(); } +| where_clause +; + +where_clause +: WHERE where_predicates { $$ = mk_node("WhereClause", 1, $2); } +| WHERE where_predicates ',' { $$ = mk_node("WhereClause", 1, $2); } +; + +where_predicates +: where_predicate { $$ = mk_node("WherePredicates", 1, $1); } +| where_predicates ',' where_predicate { $$ = ext_node($1, 1, $3); } +; + +where_predicate +: maybe_for_lifetimes lifetime ':' bounds { $$ = mk_node("WherePredicate", 3, $1, $2, $4); } +| maybe_for_lifetimes ty ':' ty_param_bounds { $$ = mk_node("WherePredicate", 3, $1, $2, $4); } +; + +maybe_for_lifetimes +: FOR '<' lifetimes '>' { $$ = mk_none(); } +| %prec FORTYPE %empty { $$ = mk_none(); } + +ty_params +: ty_param { $$ = mk_node("TyParams", 1, $1); } +| ty_params ',' ty_param { $$ = ext_node($1, 1, $3); } +; + +// A path with no type parameters; e.g. `foo::bar::Baz` +// +// These show up in 'use' view-items, because these are processed +// without respect to types. +path_no_types_allowed +: ident { $$ = mk_node("ViewPath", 1, $1); } +| MOD_SEP ident { $$ = mk_node("ViewPath", 1, $2); } +| SELF { $$ = mk_node("ViewPath", 1, mk_atom("Self")); } +| MOD_SEP SELF { $$ = mk_node("ViewPath", 1, mk_atom("Self")); } +| SUPER { $$ = mk_node("ViewPath", 1, mk_atom("Super")); } +| MOD_SEP SUPER { $$ = mk_node("ViewPath", 1, mk_atom("Super")); } +| path_no_types_allowed MOD_SEP ident { $$ = ext_node($1, 1, $3); } +; + +// A path with a lifetime and type parameters, with no double colons +// before the type parameters; e.g. `foo::bar<'a>::Baz` +// +// These show up in "trait references", the components of +// type-parameter bounds lists, as well as in the prefix of the +// path_generic_args_and_bounds rule, which is the full form of a +// named typed expression. +// +// They do not have (nor need) an extra '::' before '<' because +// unlike in expr context, there are no "less-than" type exprs to +// be ambiguous with. +path_generic_args_without_colons +: %prec IDENT + ident { $$ = mk_node("components", 1, $1); } +| %prec IDENT + ident generic_args { $$ = mk_node("components", 2, $1, $2); } +| %prec IDENT + ident '(' maybe_ty_sums ')' ret_ty { $$ = mk_node("components", 2, $1, $3); } +| %prec IDENT + path_generic_args_without_colons MOD_SEP ident { $$ = ext_node($1, 1, $3); } +| %prec IDENT + path_generic_args_without_colons MOD_SEP ident generic_args { $$ = ext_node($1, 2, $3, $4); } +| %prec IDENT + path_generic_args_without_colons MOD_SEP ident '(' maybe_ty_sums ')' ret_ty { $$ = ext_node($1, 2, $3, $5); } +; + +generic_args +: '<' generic_values '>' { $$ = $2; } +| '<' generic_values SHR { push_back('>'); $$ = $2; } +| '<' generic_values GE { push_back('='); $$ = $2; } +| '<' generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; } +// If generic_args starts with "<<", the first arg must be a +// TyQualifiedPath because that's the only type that can start with a +// '<'. This rule parses that as the first ty_sum and then continues +// with the rest of generic_values. +| SHL ty_qualified_path_and_generic_values '>' { $$ = $2; } +| SHL ty_qualified_path_and_generic_values SHR { push_back('>'); $$ = $2; } +| SHL ty_qualified_path_and_generic_values GE { push_back('='); $$ = $2; } +| SHL ty_qualified_path_and_generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; } +; + +generic_values +: maybe_ty_sums_and_or_bindings { $$ = mk_node("GenericValues", 1, $1); } +; + +maybe_ty_sums_and_or_bindings +: ty_sums +| ty_sums ',' +| ty_sums ',' bindings { $$ = mk_node("TySumsAndBindings", 2, $1, $3); } +| bindings +| bindings ',' +| %empty { $$ = mk_none(); } +; + +maybe_bindings +: ',' bindings { $$ = $2; } +| %empty { $$ = mk_none(); } +; + +//////////////////////////////////////////////////////////////////////// +// Part 2: Patterns +//////////////////////////////////////////////////////////////////////// + +pat +: UNDERSCORE { $$ = mk_atom("PatWild"); } +| '&' pat { $$ = mk_node("PatRegion", 1, $2); } +| '&' MUT pat { $$ = mk_node("PatRegion", 1, $3); } +| ANDAND pat { $$ = mk_node("PatRegion", 1, mk_node("PatRegion", 1, $2)); } +| '(' ')' { $$ = mk_atom("PatUnit"); } +| '(' pat_tup ')' { $$ = mk_node("PatTup", 1, $2); } +| '[' pat_vec ']' { $$ = mk_node("PatVec", 1, $2); } +| lit_or_path +| lit_or_path DOTDOTDOT lit_or_path { $$ = mk_node("PatRange", 2, $1, $3); } +| path_expr '{' pat_struct '}' { $$ = mk_node("PatStruct", 2, $1, $3); } +| path_expr '(' ')' { $$ = mk_node("PatEnum", 2, $1, mk_none()); } +| path_expr '(' pat_tup ')' { $$ = mk_node("PatEnum", 2, $1, $3); } +| path_expr '!' maybe_ident delimited_token_trees { $$ = mk_node("PatMac", 3, $1, $3, $4); } +| binding_mode ident { $$ = mk_node("PatIdent", 2, $1, $2); } +| ident '@' pat { $$ = mk_node("PatIdent", 3, mk_node("BindByValue", 1, mk_atom("MutImmutable")), $1, $3); } +| binding_mode ident '@' pat { $$ = mk_node("PatIdent", 3, $1, $2, $4); } +| BOX pat { $$ = mk_node("PatUniq", 1, $2); } +| '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("PatQualifiedPath", 3, $2, $3, $6); } +| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident +{ + $$ = mk_node("PatQualifiedPath", 3, mk_node("PatQualifiedPath", 3, $2, $3, $6), $7, $10); +} +; + +pats_or +: pat { $$ = mk_node("Pats", 1, $1); } +| pats_or '|' pat { $$ = ext_node($1, 1, $3); } +; + +binding_mode +: REF { $$ = mk_node("BindByRef", 1, mk_atom("MutImmutable")); } +| REF MUT { $$ = mk_node("BindByRef", 1, mk_atom("MutMutable")); } +| MUT { $$ = mk_node("BindByValue", 1, mk_atom("MutMutable")); } +; + +lit_or_path +: path_expr { $$ = mk_node("PatLit", 1, $1); } +| lit { $$ = mk_node("PatLit", 1, $1); } +| '-' lit { $$ = mk_node("PatLit", 1, $2); } +; + +pat_field +: ident { $$ = mk_node("PatField", 1, $1); } +| binding_mode ident { $$ = mk_node("PatField", 2, $1, $2); } +| BOX ident { $$ = mk_node("PatField", 2, mk_atom("box"), $2); } +| BOX binding_mode ident { $$ = mk_node("PatField", 3, mk_atom("box"), $2, $3); } +| ident ':' pat { $$ = mk_node("PatField", 2, $1, $3); } +| binding_mode ident ':' pat { $$ = mk_node("PatField", 3, $1, $2, $4); } +| LIT_INTEGER ':' pat { $$ = mk_node("PatField", 2, mk_atom(yytext), $3); } +; + +pat_fields +: pat_field { $$ = mk_node("PatFields", 1, $1); } +| pat_fields ',' pat_field { $$ = ext_node($1, 1, $3); } +; + +pat_struct +: pat_fields { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); } +| pat_fields ',' { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); } +| pat_fields ',' DOTDOT { $$ = mk_node("PatStruct", 2, $1, mk_atom("true")); } +| DOTDOT { $$ = mk_node("PatStruct", 1, mk_atom("true")); } +| %empty { $$ = mk_node("PatStruct", 1, mk_none()); } +; + +pat_tup +: pat_tup_elts { $$ = mk_node("PatTup", 2, $1, mk_none()); } +| pat_tup_elts ',' { $$ = mk_node("PatTup", 2, $1, mk_none()); } +| pat_tup_elts DOTDOT { $$ = mk_node("PatTup", 2, $1, mk_none()); } +| pat_tup_elts ',' DOTDOT { $$ = mk_node("PatTup", 2, $1, mk_none()); } +| pat_tup_elts DOTDOT ',' pat_tup_elts { $$ = mk_node("PatTup", 2, $1, $4); } +| pat_tup_elts DOTDOT ',' pat_tup_elts ',' { $$ = mk_node("PatTup", 2, $1, $4); } +| pat_tup_elts ',' DOTDOT ',' pat_tup_elts { $$ = mk_node("PatTup", 2, $1, $5); } +| pat_tup_elts ',' DOTDOT ',' pat_tup_elts ',' { $$ = mk_node("PatTup", 2, $1, $5); } +| DOTDOT ',' pat_tup_elts { $$ = mk_node("PatTup", 2, mk_none(), $3); } +| DOTDOT ',' pat_tup_elts ',' { $$ = mk_node("PatTup", 2, mk_none(), $3); } +| DOTDOT { $$ = mk_node("PatTup", 2, mk_none(), mk_none()); } +; + +pat_tup_elts +: pat { $$ = mk_node("PatTupElts", 1, $1); } +| pat_tup_elts ',' pat { $$ = ext_node($1, 1, $3); } +; + +pat_vec +: pat_vec_elts { $$ = mk_node("PatVec", 2, $1, mk_none()); } +| pat_vec_elts ',' { $$ = mk_node("PatVec", 2, $1, mk_none()); } +| pat_vec_elts DOTDOT { $$ = mk_node("PatVec", 2, $1, mk_none()); } +| pat_vec_elts ',' DOTDOT { $$ = mk_node("PatVec", 2, $1, mk_none()); } +| pat_vec_elts DOTDOT ',' pat_vec_elts { $$ = mk_node("PatVec", 2, $1, $4); } +| pat_vec_elts DOTDOT ',' pat_vec_elts ',' { $$ = mk_node("PatVec", 2, $1, $4); } +| pat_vec_elts ',' DOTDOT ',' pat_vec_elts { $$ = mk_node("PatVec", 2, $1, $5); } +| pat_vec_elts ',' DOTDOT ',' pat_vec_elts ',' { $$ = mk_node("PatVec", 2, $1, $5); } +| DOTDOT ',' pat_vec_elts { $$ = mk_node("PatVec", 2, mk_none(), $3); } +| DOTDOT ',' pat_vec_elts ',' { $$ = mk_node("PatVec", 2, mk_none(), $3); } +| DOTDOT { $$ = mk_node("PatVec", 2, mk_none(), mk_none()); } +| %empty { $$ = mk_node("PatVec", 2, mk_none(), mk_none()); } +; + +pat_vec_elts +: pat { $$ = mk_node("PatVecElts", 1, $1); } +| pat_vec_elts ',' pat { $$ = ext_node($1, 1, $3); } +; + +//////////////////////////////////////////////////////////////////////// +// Part 3: Types +//////////////////////////////////////////////////////////////////////// + +ty +: ty_prim +| ty_closure +| '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, $2, $3, $6); } +| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, mk_node("TyQualifiedPath", 3, $2, $3, $6), $7, $10); } +| '(' ty_sums ')' { $$ = mk_node("TyTup", 1, $2); } +| '(' ty_sums ',' ')' { $$ = mk_node("TyTup", 1, $2); } +| '(' ')' { $$ = mk_atom("TyNil"); } +; + +ty_prim +: %prec IDENT path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("false")), $1); } +| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("true")), $2); } +| %prec IDENT SELF MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("self", 1, mk_atom("true")), $3); } +| %prec IDENT path_generic_args_without_colons '!' maybe_ident delimited_token_trees { $$ = mk_node("TyMacro", 3, $1, $3, $4); } +| %prec IDENT MOD_SEP path_generic_args_without_colons '!' maybe_ident delimited_token_trees { $$ = mk_node("TyMacro", 3, $2, $4, $5); } +| BOX ty { $$ = mk_node("TyBox", 1, $2); } +| '*' maybe_mut_or_const ty { $$ = mk_node("TyPtr", 2, $2, $3); } +| '&' ty { $$ = mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2); } +| '&' MUT ty { $$ = mk_node("TyRptr", 2, mk_atom("MutMutable"), $3); } +| ANDAND ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2)); } +| ANDAND MUT ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutMutable"), $3)); } +| '&' lifetime maybe_mut ty { $$ = mk_node("TyRptr", 3, $2, $3, $4); } +| ANDAND lifetime maybe_mut ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 3, $2, $3, $4)); } +| '[' ty ']' { $$ = mk_node("TyVec", 1, $2); } +| '[' ty ',' DOTDOT expr ']' { $$ = mk_node("TyFixedLengthVec", 2, $2, $5); } +| '[' ty ';' expr ']' { $$ = mk_node("TyFixedLengthVec", 2, $2, $4); } +| TYPEOF '(' expr ')' { $$ = mk_node("TyTypeof", 1, $3); } +| UNDERSCORE { $$ = mk_atom("TyInfer"); } +| ty_bare_fn +| for_in_type +; + +ty_bare_fn +: FN ty_fn_decl { $$ = $2; } +| UNSAFE FN ty_fn_decl { $$ = $3; } +| EXTERN maybe_abi FN ty_fn_decl { $$ = $4; } +| UNSAFE EXTERN maybe_abi FN ty_fn_decl { $$ = $5; } +; + +ty_fn_decl +: generic_params fn_anon_params ret_ty { $$ = mk_node("TyFnDecl", 3, $1, $2, $3); } +; + +ty_closure +: UNSAFE '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node("TyClosure", 3, $3, $5, $6); } +| '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node("TyClosure", 3, $2, $4, $5); } +| UNSAFE OROR maybe_bounds ret_ty { $$ = mk_node("TyClosure", 2, $3, $4); } +| OROR maybe_bounds ret_ty { $$ = mk_node("TyClosure", 2, $2, $3); } +; + +for_in_type +: FOR '<' maybe_lifetimes '>' for_in_type_suffix { $$ = mk_node("ForInType", 2, $3, $5); } +; + +for_in_type_suffix +: ty_bare_fn +| trait_ref +| ty_closure +; + +maybe_mut +: MUT { $$ = mk_atom("MutMutable"); } +| %prec MUT %empty { $$ = mk_atom("MutImmutable"); } +; + +maybe_mut_or_const +: MUT { $$ = mk_atom("MutMutable"); } +| CONST { $$ = mk_atom("MutImmutable"); } +| %empty { $$ = mk_atom("MutImmutable"); } +; + +ty_qualified_path_and_generic_values +: ty_qualified_path maybe_bindings +{ + $$ = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 1, mk_node("TySum", 1, $1)), $2); +} +| ty_qualified_path ',' ty_sums maybe_bindings +{ + $$ = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 2, $1, $3), $4); +} +; + +ty_qualified_path +: ty_sum AS trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, $1, $3, $6); } +| ty_sum AS trait_ref '>' MOD_SEP ident '+' ty_param_bounds { $$ = mk_node("TyQualifiedPath", 3, $1, $3, $6); } +; + +maybe_ty_sums +: ty_sums +| ty_sums ',' +| %empty { $$ = mk_none(); } +; + +ty_sums +: ty_sum { $$ = mk_node("TySums", 1, $1); } +| ty_sums ',' ty_sum { $$ = ext_node($1, 1, $3); } +; + +ty_sum +: ty_sum_elt { $$ = mk_node("TySum", 1, $1); } +| ty_sum '+' ty_sum_elt { $$ = ext_node($1, 1, $3); } +; + +ty_sum_elt +: ty +| lifetime +; + +ty_prim_sum +: ty_prim_sum_elt { $$ = mk_node("TySum", 1, $1); } +| ty_prim_sum '+' ty_prim_sum_elt { $$ = ext_node($1, 1, $3); } +; + +ty_prim_sum_elt +: ty_prim +| lifetime +; + +maybe_ty_param_bounds +: ':' ty_param_bounds { $$ = $2; } +| %empty { $$ = mk_none(); } +; + +ty_param_bounds +: boundseq +| %empty { $$ = mk_none(); } +; + +boundseq +: polybound +| boundseq '+' polybound { $$ = ext_node($1, 1, $3); } +; + +polybound +: FOR '<' maybe_lifetimes '>' bound { $$ = mk_node("PolyBound", 2, $3, $5); } +| bound +| '?' FOR '<' maybe_lifetimes '>' bound { $$ = mk_node("PolyBound", 2, $4, $6); } +| '?' bound { $$ = $2; } +; + +bindings +: binding { $$ = mk_node("Bindings", 1, $1); } +| bindings ',' binding { $$ = ext_node($1, 1, $3); } +; + +binding +: ident '=' ty { mk_node("Binding", 2, $1, $3); } +; + +ty_param +: ident maybe_ty_param_bounds maybe_ty_default { $$ = mk_node("TyParam", 3, $1, $2, $3); } +| ident '?' ident maybe_ty_param_bounds maybe_ty_default { $$ = mk_node("TyParam", 4, $1, $3, $4, $5); } +; + +maybe_bounds +: %prec SHIFTPLUS + ':' bounds { $$ = $2; } +| %prec SHIFTPLUS %empty { $$ = mk_none(); } +; + +bounds +: bound { $$ = mk_node("bounds", 1, $1); } +| bounds '+' bound { $$ = ext_node($1, 1, $3); } +; + +bound +: lifetime +| trait_ref +; + +maybe_ltbounds +: %prec SHIFTPLUS + ':' ltbounds { $$ = $2; } +| %empty { $$ = mk_none(); } +; + +ltbounds +: lifetime { $$ = mk_node("ltbounds", 1, $1); } +| ltbounds '+' lifetime { $$ = ext_node($1, 1, $3); } +; + +maybe_ty_default +: '=' ty_sum { $$ = mk_node("TyDefault", 1, $2); } +| %empty { $$ = mk_none(); } +; + +maybe_lifetimes +: lifetimes +| lifetimes ',' +| %empty { $$ = mk_none(); } +; + +lifetimes +: lifetime_and_bounds { $$ = mk_node("Lifetimes", 1, $1); } +| lifetimes ',' lifetime_and_bounds { $$ = ext_node($1, 1, $3); } +; + +lifetime_and_bounds +: LIFETIME maybe_ltbounds { $$ = mk_node("lifetime", 2, mk_atom(yytext), $2); } +| STATIC_LIFETIME { $$ = mk_atom("static_lifetime"); } +; + +lifetime +: LIFETIME { $$ = mk_node("lifetime", 1, mk_atom(yytext)); } +| STATIC_LIFETIME { $$ = mk_atom("static_lifetime"); } +; + +trait_ref +: %prec IDENT path_generic_args_without_colons +| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = $2; } +; + +//////////////////////////////////////////////////////////////////////// +// Part 4: Blocks, statements, and expressions +//////////////////////////////////////////////////////////////////////// + +inner_attrs_and_block +: '{' maybe_inner_attrs maybe_stmts '}' { $$ = mk_node("ExprBlock", 2, $2, $3); } +; + +block +: '{' maybe_stmts '}' { $$ = mk_node("ExprBlock", 1, $2); } +; + +maybe_stmts +: stmts +| stmts nonblock_expr { $$ = ext_node($1, 1, $2); } +| nonblock_expr +| %empty { $$ = mk_none(); } +; + +// There are two sub-grammars within a "stmts: exprs" derivation +// depending on whether each stmt-expr is a block-expr form; this is to +// handle the "semicolon rule" for stmt sequencing that permits +// writing +// +// if foo { bar } 10 +// +// as a sequence of two stmts (one if-expr stmt, one lit-10-expr +// stmt). Unfortunately by permitting juxtaposition of exprs in +// sequence like that, the non-block expr grammar has to have a +// second limited sub-grammar that excludes the prefix exprs that +// are ambiguous with binops. That is to say: +// +// {10} - 1 +// +// should parse as (progn (progn 10) (- 1)) not (- (progn 10) 1), that +// is to say, two statements rather than one, at least according to +// the mainline rust parser. +// +// So we wind up with a 3-way split in exprs that occur in stmt lists: +// block, nonblock-prefix, and nonblock-nonprefix. +// +// In non-stmts contexts, expr can relax this trichotomy. + +stmts +: stmt { $$ = mk_node("stmts", 1, $1); } +| stmts stmt { $$ = ext_node($1, 1, $2); } +; + +stmt +: maybe_outer_attrs let { $$ = $2; } +| stmt_item +| PUB stmt_item { $$ = $2; } +| outer_attrs stmt_item { $$ = $2; } +| outer_attrs PUB stmt_item { $$ = $3; } +| full_block_expr +| maybe_outer_attrs block { $$ = $2; } +| nonblock_expr ';' +| outer_attrs nonblock_expr ';' { $$ = $2; } +| ';' { $$ = mk_none(); } +; + +maybe_exprs +: exprs +| exprs ',' +| %empty { $$ = mk_none(); } +; + +maybe_expr +: expr +| %empty { $$ = mk_none(); } +; + +exprs +: expr { $$ = mk_node("exprs", 1, $1); } +| exprs ',' expr { $$ = ext_node($1, 1, $3); } +; + +path_expr +: path_generic_args_with_colons +| MOD_SEP path_generic_args_with_colons { $$ = $2; } +| SELF MOD_SEP path_generic_args_with_colons { $$ = mk_node("SelfPath", 1, $3); } +; + +// A path with a lifetime and type parameters with double colons before +// the type parameters; e.g. `foo::bar::<'a>::Baz::` +// +// These show up in expr context, in order to disambiguate from "less-than" +// expressions. +path_generic_args_with_colons +: ident { $$ = mk_node("components", 1, $1); } +| SUPER { $$ = mk_atom("Super"); } +| path_generic_args_with_colons MOD_SEP ident { $$ = ext_node($1, 1, $3); } +| path_generic_args_with_colons MOD_SEP SUPER { $$ = ext_node($1, 1, mk_atom("Super")); } +| path_generic_args_with_colons MOD_SEP generic_args { $$ = ext_node($1, 1, $3); } +; + +// the braces-delimited macro is a block_expr so it doesn't appear here +macro_expr +: path_expr '!' maybe_ident parens_delimited_token_trees { $$ = mk_node("MacroExpr", 3, $1, $3, $4); } +| path_expr '!' maybe_ident brackets_delimited_token_trees { $$ = mk_node("MacroExpr", 3, $1, $3, $4); } +; + +nonblock_expr +: lit { $$ = mk_node("ExprLit", 1, $1); } +| %prec IDENT + path_expr { $$ = mk_node("ExprPath", 1, $1); } +| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } +| macro_expr { $$ = mk_node("ExprMac", 1, $1); } +| path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); } +| nonblock_expr '?' { $$ = mk_node("ExprTry", 1, $1); } +| nonblock_expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } +| nonblock_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } +| nonblock_expr '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } +| nonblock_expr '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); } +| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); } +| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); } +| CONTINUE { $$ = mk_node("ExprAgain", 0); } +| CONTINUE lifetime { $$ = mk_node("ExprAgain", 1, $2); } +| RETURN { $$ = mk_node("ExprRet", 0); } +| RETURN expr { $$ = mk_node("ExprRet", 1, $2); } +| BREAK { $$ = mk_node("ExprBreak", 0); } +| BREAK lifetime { $$ = mk_node("ExprBreak", 1, $2); } +| YIELD { $$ = mk_node("ExprYield", 0); } +| YIELD expr { $$ = mk_node("ExprYield", 1, $2); } +| nonblock_expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); } +| nonblock_expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); } +| nonblock_expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); } +| nonblock_expr MINUSEQ expr { $$ = mk_node("ExprAssignSub", 2, $1, $3); } +| nonblock_expr ANDEQ expr { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); } +| nonblock_expr OREQ expr { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); } +| nonblock_expr PLUSEQ expr { $$ = mk_node("ExprAssignAdd", 2, $1, $3); } +| nonblock_expr STAREQ expr { $$ = mk_node("ExprAssignMul", 2, $1, $3); } +| nonblock_expr SLASHEQ expr { $$ = mk_node("ExprAssignDiv", 2, $1, $3); } +| nonblock_expr CARETEQ expr { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); } +| nonblock_expr PERCENTEQ expr { $$ = mk_node("ExprAssignRem", 2, $1, $3); } +| nonblock_expr OROR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); } +| nonblock_expr ANDAND expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); } +| nonblock_expr EQEQ expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); } +| nonblock_expr NE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); } +| nonblock_expr '<' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); } +| nonblock_expr '>' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); } +| nonblock_expr LE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); } +| nonblock_expr GE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); } +| nonblock_expr '|' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); } +| nonblock_expr '^' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); } +| nonblock_expr '&' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); } +| nonblock_expr SHL expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); } +| nonblock_expr SHR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); } +| nonblock_expr '+' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); } +| nonblock_expr '-' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); } +| nonblock_expr '*' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); } +| nonblock_expr '/' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); } +| nonblock_expr '%' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); } +| nonblock_expr DOTDOT { $$ = mk_node("ExprRange", 2, $1, mk_none()); } +| nonblock_expr DOTDOT expr { $$ = mk_node("ExprRange", 2, $1, $3); } +| DOTDOT expr { $$ = mk_node("ExprRange", 2, mk_none(), $2); } +| DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } +| nonblock_expr AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } +| nonblock_expr ':' ty { $$ = mk_node("ExprTypeAscr", 2, $1, $3); } +| BOX expr { $$ = mk_node("ExprBox", 1, $2); } +| expr_qualified_path +| nonblock_prefix_expr +; + +expr +: lit { $$ = mk_node("ExprLit", 1, $1); } +| %prec IDENT + path_expr { $$ = mk_node("ExprPath", 1, $1); } +| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } +| macro_expr { $$ = mk_node("ExprMac", 1, $1); } +| path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); } +| expr '?' { $$ = mk_node("ExprTry", 1, $1); } +| expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } +| expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } +| expr '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } +| expr '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); } +| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); } +| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); } +| CONTINUE { $$ = mk_node("ExprAgain", 0); } +| CONTINUE ident { $$ = mk_node("ExprAgain", 1, $2); } +| RETURN { $$ = mk_node("ExprRet", 0); } +| RETURN expr { $$ = mk_node("ExprRet", 1, $2); } +| BREAK { $$ = mk_node("ExprBreak", 0); } +| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); } +| YIELD { $$ = mk_node("ExprYield", 0); } +| YIELD expr { $$ = mk_node("ExprYield", 1, $2); } +| expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); } +| expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); } +| expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); } +| expr MINUSEQ expr { $$ = mk_node("ExprAssignSub", 2, $1, $3); } +| expr ANDEQ expr { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); } +| expr OREQ expr { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); } +| expr PLUSEQ expr { $$ = mk_node("ExprAssignAdd", 2, $1, $3); } +| expr STAREQ expr { $$ = mk_node("ExprAssignMul", 2, $1, $3); } +| expr SLASHEQ expr { $$ = mk_node("ExprAssignDiv", 2, $1, $3); } +| expr CARETEQ expr { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); } +| expr PERCENTEQ expr { $$ = mk_node("ExprAssignRem", 2, $1, $3); } +| expr OROR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); } +| expr ANDAND expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); } +| expr EQEQ expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); } +| expr NE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); } +| expr '<' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); } +| expr '>' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); } +| expr LE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); } +| expr GE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); } +| expr '|' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); } +| expr '^' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); } +| expr '&' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); } +| expr SHL expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); } +| expr SHR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); } +| expr '+' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); } +| expr '-' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); } +| expr '*' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); } +| expr '/' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); } +| expr '%' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); } +| expr DOTDOT { $$ = mk_node("ExprRange", 2, $1, mk_none()); } +| expr DOTDOT expr { $$ = mk_node("ExprRange", 2, $1, $3); } +| DOTDOT expr { $$ = mk_node("ExprRange", 2, mk_none(), $2); } +| DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } +| expr AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } +| expr ':' ty { $$ = mk_node("ExprTypeAscr", 2, $1, $3); } +| BOX expr { $$ = mk_node("ExprBox", 1, $2); } +| expr_qualified_path +| block_expr +| block +| nonblock_prefix_expr +; + +expr_nostruct +: lit { $$ = mk_node("ExprLit", 1, $1); } +| %prec IDENT + path_expr { $$ = mk_node("ExprPath", 1, $1); } +| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } +| macro_expr { $$ = mk_node("ExprMac", 1, $1); } +| expr_nostruct '?' { $$ = mk_node("ExprTry", 1, $1); } +| expr_nostruct '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } +| expr_nostruct '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } +| expr_nostruct '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } +| expr_nostruct '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); } +| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); } +| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); } +| CONTINUE { $$ = mk_node("ExprAgain", 0); } +| CONTINUE ident { $$ = mk_node("ExprAgain", 1, $2); } +| RETURN { $$ = mk_node("ExprRet", 0); } +| RETURN expr { $$ = mk_node("ExprRet", 1, $2); } +| BREAK { $$ = mk_node("ExprBreak", 0); } +| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); } +| YIELD { $$ = mk_node("ExprYield", 0); } +| YIELD expr { $$ = mk_node("ExprYield", 1, $2); } +| expr_nostruct '=' expr_nostruct { $$ = mk_node("ExprAssign", 2, $1, $3); } +| expr_nostruct SHLEQ expr_nostruct { $$ = mk_node("ExprAssignShl", 2, $1, $3); } +| expr_nostruct SHREQ expr_nostruct { $$ = mk_node("ExprAssignShr", 2, $1, $3); } +| expr_nostruct MINUSEQ expr_nostruct { $$ = mk_node("ExprAssignSub", 2, $1, $3); } +| expr_nostruct ANDEQ expr_nostruct { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); } +| expr_nostruct OREQ expr_nostruct { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); } +| expr_nostruct PLUSEQ expr_nostruct { $$ = mk_node("ExprAssignAdd", 2, $1, $3); } +| expr_nostruct STAREQ expr_nostruct { $$ = mk_node("ExprAssignMul", 2, $1, $3); } +| expr_nostruct SLASHEQ expr_nostruct { $$ = mk_node("ExprAssignDiv", 2, $1, $3); } +| expr_nostruct CARETEQ expr_nostruct { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); } +| expr_nostruct PERCENTEQ expr_nostruct { $$ = mk_node("ExprAssignRem", 2, $1, $3); } +| expr_nostruct OROR expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); } +| expr_nostruct ANDAND expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); } +| expr_nostruct EQEQ expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); } +| expr_nostruct NE expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); } +| expr_nostruct '<' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); } +| expr_nostruct '>' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); } +| expr_nostruct LE expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); } +| expr_nostruct GE expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); } +| expr_nostruct '|' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); } +| expr_nostruct '^' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); } +| expr_nostruct '&' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); } +| expr_nostruct SHL expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); } +| expr_nostruct SHR expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); } +| expr_nostruct '+' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); } +| expr_nostruct '-' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); } +| expr_nostruct '*' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); } +| expr_nostruct '/' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); } +| expr_nostruct '%' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); } +| expr_nostruct DOTDOT %prec RANGE { $$ = mk_node("ExprRange", 2, $1, mk_none()); } +| expr_nostruct DOTDOT expr_nostruct { $$ = mk_node("ExprRange", 2, $1, $3); } +| DOTDOT expr_nostruct { $$ = mk_node("ExprRange", 2, mk_none(), $2); } +| DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } +| expr_nostruct AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } +| expr_nostruct ':' ty { $$ = mk_node("ExprTypeAscr", 2, $1, $3); } +| BOX expr { $$ = mk_node("ExprBox", 1, $2); } +| expr_qualified_path +| block_expr +| block +| nonblock_prefix_expr_nostruct +; + +nonblock_prefix_expr_nostruct +: '-' expr_nostruct { $$ = mk_node("ExprUnary", 2, mk_atom("UnNeg"), $2); } +| '!' expr_nostruct { $$ = mk_node("ExprUnary", 2, mk_atom("UnNot"), $2); } +| '*' expr_nostruct { $$ = mk_node("ExprUnary", 2, mk_atom("UnDeref"), $2); } +| '&' maybe_mut expr_nostruct { $$ = mk_node("ExprAddrOf", 2, $2, $3); } +| ANDAND maybe_mut expr_nostruct { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); } +| lambda_expr_nostruct +| MOVE lambda_expr_nostruct { $$ = $2; } +; + +nonblock_prefix_expr +: '-' expr { $$ = mk_node("ExprUnary", 2, mk_atom("UnNeg"), $2); } +| '!' expr { $$ = mk_node("ExprUnary", 2, mk_atom("UnNot"), $2); } +| '*' expr { $$ = mk_node("ExprUnary", 2, mk_atom("UnDeref"), $2); } +| '&' maybe_mut expr { $$ = mk_node("ExprAddrOf", 2, $2, $3); } +| ANDAND maybe_mut expr { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); } +| lambda_expr +| MOVE lambda_expr { $$ = $2; } +; + +expr_qualified_path +: '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_qpath_params +{ + $$ = mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7); +} +| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident +{ + $$ = mk_node("ExprQualifiedPath", 3, mk_node("ExprQualifiedPath", 3, $2, $3, $6), $7, $10); +} +| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident generic_args maybe_as_trait_ref '>' MOD_SEP ident +{ + $$ = mk_node("ExprQualifiedPath", 3, mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7), $8, $11); +} +| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident generic_args +{ + $$ = mk_node("ExprQualifiedPath", 4, mk_node("ExprQualifiedPath", 3, $2, $3, $6), $7, $10, $11); +} +| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident generic_args maybe_as_trait_ref '>' MOD_SEP ident generic_args +{ + $$ = mk_node("ExprQualifiedPath", 4, mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7), $8, $11, $12); +} + +maybe_qpath_params +: MOD_SEP generic_args { $$ = $2; } +| %empty { $$ = mk_none(); } +; + +maybe_as_trait_ref +: AS trait_ref { $$ = $2; } +| %empty { $$ = mk_none(); } +; + +lambda_expr +: %prec LAMBDA + OROR ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } +| %prec LAMBDA + '|' '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $3, $4); } +| %prec LAMBDA + '|' inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $2, $4, $5); } +| %prec LAMBDA + '|' inferrable_params OROR lambda_expr_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $2, mk_none(), $4); } +; + +lambda_expr_no_first_bar +: %prec LAMBDA + '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } +| %prec LAMBDA + inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $1, $3, $4); } +| %prec LAMBDA + inferrable_params OROR lambda_expr_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $1, mk_none(), $3); } +; + +lambda_expr_nostruct +: %prec LAMBDA + OROR expr_nostruct { $$ = mk_node("ExprFnBlock", 2, mk_none(), $2); } +| %prec LAMBDA + '|' '|' ret_ty expr_nostruct { $$ = mk_node("ExprFnBlock", 3, mk_none(), $3, $4); } +| %prec LAMBDA + '|' inferrable_params '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, $2, $4); } +| %prec LAMBDA + '|' inferrable_params OROR lambda_expr_nostruct_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $2, mk_none(), $4); } +; + +lambda_expr_nostruct_no_first_bar +: %prec LAMBDA + '|' ret_ty expr_nostruct { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } +| %prec LAMBDA + inferrable_params '|' ret_ty expr_nostruct { $$ = mk_node("ExprFnBlock", 3, $1, $3, $4); } +| %prec LAMBDA + inferrable_params OROR lambda_expr_nostruct_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $1, mk_none(), $3); } +; + +vec_expr +: maybe_exprs +| exprs ';' expr { $$ = mk_node("VecRepeat", 2, $1, $3); } +; + +struct_expr_fields +: field_inits +| field_inits ',' +| maybe_field_inits default_field_init { $$ = ext_node($1, 1, $2); } +| %empty { $$ = mk_none(); } +; + +maybe_field_inits +: field_inits +| field_inits ',' +| %empty { $$ = mk_none(); } +; + +field_inits +: field_init { $$ = mk_node("FieldInits", 1, $1); } +| field_inits ',' field_init { $$ = ext_node($1, 1, $3); } +; + +field_init +: ident { $$ = mk_node("FieldInit", 1, $1); } +| ident ':' expr { $$ = mk_node("FieldInit", 2, $1, $3); } +| LIT_INTEGER ':' expr { $$ = mk_node("FieldInit", 2, mk_atom(yytext), $3); } +; + +default_field_init +: DOTDOT expr { $$ = mk_node("DefaultFieldInit", 1, $2); } +; + +block_expr +: expr_match +| expr_if +| expr_if_let +| expr_while +| expr_while_let +| expr_loop +| expr_for +| UNSAFE block { $$ = mk_node("UnsafeBlock", 1, $2); } +| path_expr '!' maybe_ident braces_delimited_token_trees { $$ = mk_node("Macro", 3, $1, $3, $4); } +; + +full_block_expr +: block_expr +| block_expr_dot +; + +block_expr_dot +: block_expr '.' path_generic_args_with_colons %prec IDENT { $$ = mk_node("ExprField", 2, $1, $3); } +| block_expr_dot '.' path_generic_args_with_colons %prec IDENT { $$ = mk_node("ExprField", 2, $1, $3); } +| block_expr '.' path_generic_args_with_colons '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 3, $1, $3, $5); } +| block_expr_dot '.' path_generic_args_with_colons '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 3, $1, $3, $5); } +| block_expr '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 3, $1, $3, $5); } +| block_expr_dot '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 3, $1, $3, $5); } +| block_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } +| block_expr_dot '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } +; + +expr_match +: MATCH expr_nostruct '{' '}' { $$ = mk_node("ExprMatch", 1, $2); } +| MATCH expr_nostruct '{' match_clauses '}' { $$ = mk_node("ExprMatch", 2, $2, $4); } +| MATCH expr_nostruct '{' match_clauses nonblock_match_clause '}' { $$ = mk_node("ExprMatch", 2, $2, ext_node($4, 1, $5)); } +| MATCH expr_nostruct '{' nonblock_match_clause '}' { $$ = mk_node("ExprMatch", 2, $2, mk_node("Arms", 1, $4)); } +; + +match_clauses +: match_clause { $$ = mk_node("Arms", 1, $1); } +| match_clauses match_clause { $$ = ext_node($1, 1, $2); } +; + +match_clause +: nonblock_match_clause ',' +| block_match_clause +| block_match_clause ',' +; + +nonblock_match_clause +: maybe_outer_attrs pats_or maybe_guard FAT_ARROW nonblock_expr { $$ = mk_node("ArmNonblock", 4, $1, $2, $3, $5); } +| maybe_outer_attrs pats_or maybe_guard FAT_ARROW block_expr_dot { $$ = mk_node("ArmNonblock", 4, $1, $2, $3, $5); } +; + +block_match_clause +: maybe_outer_attrs pats_or maybe_guard FAT_ARROW block { $$ = mk_node("ArmBlock", 4, $1, $2, $3, $5); } +| maybe_outer_attrs pats_or maybe_guard FAT_ARROW block_expr { $$ = mk_node("ArmBlock", 4, $1, $2, $3, $5); } +; + +maybe_guard +: IF expr_nostruct { $$ = $2; } +| %empty { $$ = mk_none(); } +; + +expr_if +: IF expr_nostruct block { $$ = mk_node("ExprIf", 2, $2, $3); } +| IF expr_nostruct block ELSE block_or_if { $$ = mk_node("ExprIf", 3, $2, $3, $5); } +; + +expr_if_let +: IF LET pat '=' expr_nostruct block { $$ = mk_node("ExprIfLet", 3, $3, $5, $6); } +| IF LET pat '=' expr_nostruct block ELSE block_or_if { $$ = mk_node("ExprIfLet", 4, $3, $5, $6, $8); } +; + +block_or_if +: block +| expr_if +| expr_if_let +; + +expr_while +: maybe_label WHILE expr_nostruct block { $$ = mk_node("ExprWhile", 3, $1, $3, $4); } +; + +expr_while_let +: maybe_label WHILE LET pat '=' expr_nostruct block { $$ = mk_node("ExprWhileLet", 4, $1, $4, $6, $7); } +; + +expr_loop +: maybe_label LOOP block { $$ = mk_node("ExprLoop", 2, $1, $3); } +; + +expr_for +: maybe_label FOR pat IN expr_nostruct block { $$ = mk_node("ExprForLoop", 4, $1, $3, $5, $6); } +; + +maybe_label +: lifetime ':' +| %empty { $$ = mk_none(); } +; + +let +: LET pat maybe_ty_ascription maybe_init_expr ';' { $$ = mk_node("DeclLocal", 3, $2, $3, $4); } +; + +//////////////////////////////////////////////////////////////////////// +// Part 5: Macros and misc. rules +//////////////////////////////////////////////////////////////////////// + +lit +: LIT_BYTE { $$ = mk_node("LitByte", 1, mk_atom(yytext)); } +| LIT_CHAR { $$ = mk_node("LitChar", 1, mk_atom(yytext)); } +| LIT_INTEGER { $$ = mk_node("LitInteger", 1, mk_atom(yytext)); } +| LIT_FLOAT { $$ = mk_node("LitFloat", 1, mk_atom(yytext)); } +| TRUE { $$ = mk_node("LitBool", 1, mk_atom(yytext)); } +| FALSE { $$ = mk_node("LitBool", 1, mk_atom(yytext)); } +| str +; + +str +: LIT_STR { $$ = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("CookedStr")); } +| LIT_STR_RAW { $$ = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("RawStr")); } +| LIT_BYTE_STR { $$ = mk_node("LitByteStr", 1, mk_atom(yytext), mk_atom("ByteStr")); } +| LIT_BYTE_STR_RAW { $$ = mk_node("LitByteStr", 1, mk_atom(yytext), mk_atom("RawByteStr")); } +; + +maybe_ident +: %empty { $$ = mk_none(); } +| ident +; + +ident +: IDENT { $$ = mk_node("ident", 1, mk_atom(yytext)); } +// Weak keywords that can be used as identifiers +| CATCH { $$ = mk_node("ident", 1, mk_atom(yytext)); } +| DEFAULT { $$ = mk_node("ident", 1, mk_atom(yytext)); } +| UNION { $$ = mk_node("ident", 1, mk_atom(yytext)); } +; + +unpaired_token +: SHL { $$ = mk_atom(yytext); } +| SHR { $$ = mk_atom(yytext); } +| LE { $$ = mk_atom(yytext); } +| EQEQ { $$ = mk_atom(yytext); } +| NE { $$ = mk_atom(yytext); } +| GE { $$ = mk_atom(yytext); } +| ANDAND { $$ = mk_atom(yytext); } +| OROR { $$ = mk_atom(yytext); } +| LARROW { $$ = mk_atom(yytext); } +| SHLEQ { $$ = mk_atom(yytext); } +| SHREQ { $$ = mk_atom(yytext); } +| MINUSEQ { $$ = mk_atom(yytext); } +| ANDEQ { $$ = mk_atom(yytext); } +| OREQ { $$ = mk_atom(yytext); } +| PLUSEQ { $$ = mk_atom(yytext); } +| STAREQ { $$ = mk_atom(yytext); } +| SLASHEQ { $$ = mk_atom(yytext); } +| CARETEQ { $$ = mk_atom(yytext); } +| PERCENTEQ { $$ = mk_atom(yytext); } +| DOTDOT { $$ = mk_atom(yytext); } +| DOTDOTDOT { $$ = mk_atom(yytext); } +| MOD_SEP { $$ = mk_atom(yytext); } +| RARROW { $$ = mk_atom(yytext); } +| FAT_ARROW { $$ = mk_atom(yytext); } +| LIT_BYTE { $$ = mk_atom(yytext); } +| LIT_CHAR { $$ = mk_atom(yytext); } +| LIT_INTEGER { $$ = mk_atom(yytext); } +| LIT_FLOAT { $$ = mk_atom(yytext); } +| LIT_STR { $$ = mk_atom(yytext); } +| LIT_STR_RAW { $$ = mk_atom(yytext); } +| LIT_BYTE_STR { $$ = mk_atom(yytext); } +| LIT_BYTE_STR_RAW { $$ = mk_atom(yytext); } +| IDENT { $$ = mk_atom(yytext); } +| UNDERSCORE { $$ = mk_atom(yytext); } +| LIFETIME { $$ = mk_atom(yytext); } +| SELF { $$ = mk_atom(yytext); } +| STATIC { $$ = mk_atom(yytext); } +| ABSTRACT { $$ = mk_atom(yytext); } +| ALIGNOF { $$ = mk_atom(yytext); } +| AS { $$ = mk_atom(yytext); } +| BECOME { $$ = mk_atom(yytext); } +| BREAK { $$ = mk_atom(yytext); } +| CATCH { $$ = mk_atom(yytext); } +| CRATE { $$ = mk_atom(yytext); } +| DEFAULT { $$ = mk_atom(yytext); } +| DO { $$ = mk_atom(yytext); } +| ELSE { $$ = mk_atom(yytext); } +| ENUM { $$ = mk_atom(yytext); } +| EXTERN { $$ = mk_atom(yytext); } +| FALSE { $$ = mk_atom(yytext); } +| FINAL { $$ = mk_atom(yytext); } +| FN { $$ = mk_atom(yytext); } +| FOR { $$ = mk_atom(yytext); } +| IF { $$ = mk_atom(yytext); } +| IMPL { $$ = mk_atom(yytext); } +| IN { $$ = mk_atom(yytext); } +| LET { $$ = mk_atom(yytext); } +| LOOP { $$ = mk_atom(yytext); } +| MACRO { $$ = mk_atom(yytext); } +| MATCH { $$ = mk_atom(yytext); } +| MOD { $$ = mk_atom(yytext); } +| MOVE { $$ = mk_atom(yytext); } +| MUT { $$ = mk_atom(yytext); } +| OFFSETOF { $$ = mk_atom(yytext); } +| OVERRIDE { $$ = mk_atom(yytext); } +| PRIV { $$ = mk_atom(yytext); } +| PUB { $$ = mk_atom(yytext); } +| PURE { $$ = mk_atom(yytext); } +| REF { $$ = mk_atom(yytext); } +| RETURN { $$ = mk_atom(yytext); } +| STRUCT { $$ = mk_atom(yytext); } +| SIZEOF { $$ = mk_atom(yytext); } +| SUPER { $$ = mk_atom(yytext); } +| TRUE { $$ = mk_atom(yytext); } +| TRAIT { $$ = mk_atom(yytext); } +| TYPE { $$ = mk_atom(yytext); } +| UNION { $$ = mk_atom(yytext); } +| UNSAFE { $$ = mk_atom(yytext); } +| UNSIZED { $$ = mk_atom(yytext); } +| USE { $$ = mk_atom(yytext); } +| VIRTUAL { $$ = mk_atom(yytext); } +| WHILE { $$ = mk_atom(yytext); } +| YIELD { $$ = mk_atom(yytext); } +| CONTINUE { $$ = mk_atom(yytext); } +| PROC { $$ = mk_atom(yytext); } +| BOX { $$ = mk_atom(yytext); } +| CONST { $$ = mk_atom(yytext); } +| WHERE { $$ = mk_atom(yytext); } +| TYPEOF { $$ = mk_atom(yytext); } +| INNER_DOC_COMMENT { $$ = mk_atom(yytext); } +| OUTER_DOC_COMMENT { $$ = mk_atom(yytext); } +| SHEBANG { $$ = mk_atom(yytext); } +| STATIC_LIFETIME { $$ = mk_atom(yytext); } +| ';' { $$ = mk_atom(yytext); } +| ',' { $$ = mk_atom(yytext); } +| '.' { $$ = mk_atom(yytext); } +| '@' { $$ = mk_atom(yytext); } +| '#' { $$ = mk_atom(yytext); } +| '~' { $$ = mk_atom(yytext); } +| ':' { $$ = mk_atom(yytext); } +| '$' { $$ = mk_atom(yytext); } +| '=' { $$ = mk_atom(yytext); } +| '?' { $$ = mk_atom(yytext); } +| '!' { $$ = mk_atom(yytext); } +| '<' { $$ = mk_atom(yytext); } +| '>' { $$ = mk_atom(yytext); } +| '-' { $$ = mk_atom(yytext); } +| '&' { $$ = mk_atom(yytext); } +| '|' { $$ = mk_atom(yytext); } +| '+' { $$ = mk_atom(yytext); } +| '*' { $$ = mk_atom(yytext); } +| '/' { $$ = mk_atom(yytext); } +| '^' { $$ = mk_atom(yytext); } +| '%' { $$ = mk_atom(yytext); } +; + +token_trees +: %empty { $$ = mk_node("TokenTrees", 0); } +| token_trees token_tree { $$ = ext_node($1, 1, $2); } +; + +token_tree +: delimited_token_trees +| unpaired_token { $$ = mk_node("TTTok", 1, $1); } +; + +delimited_token_trees +: parens_delimited_token_trees +| braces_delimited_token_trees +| brackets_delimited_token_trees +; + +parens_delimited_token_trees +: '(' token_trees ')' +{ + $$ = mk_node("TTDelim", 3, + mk_node("TTTok", 1, mk_atom("(")), + $2, + mk_node("TTTok", 1, mk_atom(")"))); +} +; + +braces_delimited_token_trees +: '{' token_trees '}' +{ + $$ = mk_node("TTDelim", 3, + mk_node("TTTok", 1, mk_atom("{")), + $2, + mk_node("TTTok", 1, mk_atom("}"))); +} +; + +brackets_delimited_token_trees +: '[' token_trees ']' +{ + $$ = mk_node("TTDelim", 3, + mk_node("TTTok", 1, mk_atom("[")), + $2, + mk_node("TTTok", 1, mk_atom("]"))); +} +; diff --git a/src/grammar/raw-string-literal-ambiguity.md b/src/grammar/raw-string-literal-ambiguity.md new file mode 100644 index 0000000000000..c909f2333148a --- /dev/null +++ b/src/grammar/raw-string-literal-ambiguity.md @@ -0,0 +1,64 @@ +Rust's lexical grammar is not context-free. Raw string literals are the source +of the problem. Informally, a raw string literal is an `r`, followed by `N` +hashes (where N can be zero), a quote, any characters, then a quote followed +by `N` hashes. Critically, once inside the first pair of quotes, +another quote cannot be followed by `N` consecutive hashes. e.g. +`r###""###"###` is invalid. + +This grammar describes this as best possible: + + R -> 'r' S + S -> '"' B '"' + S -> '#' S '#' + B -> . B + B -> ε + +Where `.` represents any character, and `ε` the empty string. Consider the +string `r#""#"#`. This string is not a valid raw string literal, but can be +accepted as one by the above grammar, using the derivation: + + R : #""#"# + S : ""#" + S : "# + B : # + B : ε + +(Where `T : U` means the rule `T` is applied, and `U` is the remainder of the +string.) The difficulty arises from the fact that it is fundamentally +context-sensitive. In particular, the context needed is the number of hashes. + +To prove that Rust's string literals are not context-free, we will use +the fact that context-free languages are closed under intersection with +regular languages, and the +[pumping lemma for context-free languages](https://en.wikipedia.org/wiki/Pumping_lemma_for_context-free_languages). + +Consider the regular language `R = r#+""#*"#+`. If Rust's raw string literals are +context-free, then their intersection with `R`, `R'`, should also be context-free. +Therefore, to prove that raw string literals are not context-free, +it is sufficient to prove that `R'` is not context-free. + +The language `R'` is `{r#^n""#^m"#^n | m < n}`. + +Assume `R'` *is* context-free. Then `R'` has some pumping length `p > 0` for which +the pumping lemma applies. Consider the following string `s` in `R'`: + +`r#^p""#^{p-1}"#^p` + +e.g. for `p = 2`: `s = r##""#"##` + +Then `s = uvwxy` for some choice of `uvwxy` such that `vx` is non-empty, +`|vwx| < p+1`, and `uv^iwx^iy` is in `R'` for all `i >= 0`. + +Neither `v` nor `x` can contain a `"` or `r`, as the number of these characters +in any string in `R'` is fixed. So `v` and `x` contain only hashes. +Consequently, of the three sequences of hashes, `v` and `x` combined +can only pump two of them. +If we ever choose the central sequence of hashes, then one of the outer sequences +will not grow when we pump, leading to an imbalance between the outer sequences. +Therefore, we must pump both outer sequences of hashes. However, +there are `p+2` characters between these two sequences of hashes, and `|vwx|` must +be less than `p+1`. Therefore we have a contradiction, and `R'` must not be +context-free. + +Since `R'` is not context-free, it follows that the Rust's raw string literals +must not be context-free. diff --git a/src/grammar/testparser.py b/src/grammar/testparser.py new file mode 100755 index 0000000000000..4b5a7fb9e10b5 --- /dev/null +++ b/src/grammar/testparser.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +# ignore-tidy-linelength + +import sys + +import os +import subprocess +import argparse + +# usage: testparser.py [-h] [-p PARSER [PARSER ...]] -s SOURCE_DIR + +# Parsers should read from stdin and return exit status 0 for a +# successful parse, and nonzero for an unsuccessful parse + +parser = argparse.ArgumentParser() +parser.add_argument('-p', '--parser', nargs='+') +parser.add_argument('-s', '--source-dir', nargs=1, required=True) +args = parser.parse_args(sys.argv[1:]) + +total = 0 +ok = {} +bad = {} +for parser in args.parser: + ok[parser] = 0 + bad[parser] = [] +devnull = open(os.devnull, 'w') +print("\n") + +for base, dirs, files in os.walk(args.source_dir[0]): + for f in filter(lambda p: p.endswith('.rs'), files): + p = os.path.join(base, f) + parse_fail = 'parse-fail' in p + if sys.version_info.major == 3: + lines = open(p, encoding='utf-8').readlines() + else: + lines = open(p).readlines() + if any('ignore-test' in line or 'ignore-lexer-test' in line for line in lines): + continue + total += 1 + for parser in args.parser: + if subprocess.call(parser, stdin=open(p), stderr=subprocess.STDOUT, stdout=devnull) == 0: + if parse_fail: + bad[parser].append(p) + else: + ok[parser] += 1 + else: + if parse_fail: + ok[parser] += 1 + else: + bad[parser].append(p) + parser_stats = ', '.join(['{}: {}'.format(parser, ok[parser]) for parser in args.parser]) + sys.stdout.write("\033[K\r total: {}, {}, scanned {}" + .format(total, os.path.relpath(parser_stats), os.path.relpath(p))) + +devnull.close() + +print("\n") + +for parser in args.parser: + filename = os.path.basename(parser) + '.bad' + print("writing {} files that did not yield the correct result with {} to {}".format(len(bad[parser]), parser, filename)) + with open(filename, "w") as f: + for p in bad[parser]: + f.write(p) + f.write("\n") diff --git a/src/grammar/tokens.h b/src/grammar/tokens.h new file mode 100644 index 0000000000000..297e3dc841e87 --- /dev/null +++ b/src/grammar/tokens.h @@ -0,0 +1,99 @@ +enum Token { + SHL = 257, // Parser generators reserve 0-256 for char literals + SHR, + LE, + EQEQ, + NE, + GE, + ANDAND, + OROR, + SHLEQ, + SHREQ, + MINUSEQ, + ANDEQ, + OREQ, + PLUSEQ, + STAREQ, + SLASHEQ, + CARETEQ, + PERCENTEQ, + DOTDOT, + DOTDOTDOT, + MOD_SEP, + LARROW, + RARROW, + FAT_ARROW, + LIT_BYTE, + LIT_CHAR, + LIT_INTEGER, + LIT_FLOAT, + LIT_STR, + LIT_STR_RAW, + LIT_BYTE_STR, + LIT_BYTE_STR_RAW, + IDENT, + UNDERSCORE, + LIFETIME, + + // keywords + SELF, + STATIC, + ABSTRACT, + ALIGNOF, + AS, + BECOME, + BREAK, + CATCH, + CRATE, + DEFAULT, + DO, + ELSE, + ENUM, + EXTERN, + FALSE, + FINAL, + FN, + FOR, + IF, + IMPL, + IN, + LET, + LOOP, + MACRO, + MATCH, + MOD, + MOVE, + MUT, + OFFSETOF, + OVERRIDE, + PRIV, + PUB, + PURE, + REF, + RETURN, + SIZEOF, + STRUCT, + SUPER, + UNION, + TRUE, + TRAIT, + TYPE, + UNSAFE, + UNSIZED, + USE, + VIRTUAL, + WHILE, + YIELD, + CONTINUE, + PROC, + BOX, + CONST, + WHERE, + TYPEOF, + INNER_DOC_COMMENT, + OUTER_DOC_COMMENT, + + SHEBANG, + SHEBANG_LINE, + STATIC_LIFETIME +}; diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs index d2bdda83fa998..a9c5bce4c25fc 100644 --- a/src/liballoc/borrow.rs +++ b/src/liballoc/borrow.rs @@ -207,47 +207,6 @@ impl Clone for Cow<'_, B> { } impl Cow<'_, B> { - /// Returns true if the data is borrowed, i.e. if `to_mut` would require additional work. - /// - /// # Examples - /// - /// ``` - /// #![feature(cow_is_borrowed)] - /// use std::borrow::Cow; - /// - /// let cow = Cow::Borrowed("moo"); - /// assert!(cow.is_borrowed()); - /// - /// let bull: Cow<'_, str> = Cow::Owned("...moo?".to_string()); - /// assert!(!bull.is_borrowed()); - /// ``` - #[unstable(feature = "cow_is_borrowed", issue = "65143")] - pub fn is_borrowed(&self) -> bool { - match *self { - Borrowed(_) => true, - Owned(_) => false, - } - } - - /// Returns true if the data is owned, i.e. if `to_mut` would be a no-op. - /// - /// # Examples - /// - /// ``` - /// #![feature(cow_is_borrowed)] - /// use std::borrow::Cow; - /// - /// let cow: Cow<'_, str> = Cow::Owned("moo".to_string()); - /// assert!(cow.is_owned()); - /// - /// let bull = Cow::Borrowed("...moo?"); - /// assert!(!bull.is_owned()); - /// ``` - #[unstable(feature = "cow_is_borrowed", issue = "65143")] - pub fn is_owned(&self) -> bool { - !self.is_borrowed() - } - /// Acquires a mutable reference to the owned form of the data. /// /// Clones the data if it is not already owned. diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 567b8ea722491..c61e3183409f2 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -29,8 +29,10 @@ //! Nil, //! } //! -//! let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil)))); -//! println!("{:?}", list); +//! fn main() { +//! let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil)))); +//! println!("{:?}", list); +//! } //! ``` //! //! This will print `Cons(1, Cons(2, Nil))`. @@ -142,9 +144,6 @@ impl Box { #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Box> { let layout = alloc::Layout::new::>(); - if layout.size() == 0 { - return Box(NonNull::dangling().into()) - } let ptr = unsafe { Global.alloc(layout) .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) @@ -185,16 +184,9 @@ impl Box<[T]> { #[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 = if layout.size() == 0 { - NonNull::dangling() - } else { - unsafe { - Global.alloc(layout) - .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) - .cast() - } - }; - let slice = unsafe { slice::from_raw_parts_mut(ptr.as_ptr(), len) }; + 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)) } } @@ -383,12 +375,14 @@ impl Box { /// ``` /// #![feature(box_into_raw_non_null)] /// - /// let x = Box::new(5); - /// let ptr = Box::into_raw_non_null(x); + /// fn main() { + /// let x = Box::new(5); + /// let ptr = Box::into_raw_non_null(x); /// - /// // Clean up the memory by converting the NonNull pointer back - /// // into a Box and letting the Box be dropped. - /// let x = unsafe { Box::from_raw(ptr.as_ptr()) }; + /// // Clean up the memory by converting the NonNull pointer back + /// // into a Box and letting the Box be dropped. + /// let x = unsafe { Box::from_raw(ptr.as_ptr()) }; + /// } /// ``` #[unstable(feature = "box_into_raw_non_null", issue = "47336")] #[inline] @@ -434,19 +428,23 @@ impl Box { /// Simple usage: /// /// ``` - /// let x = Box::new(41); - /// let static_ref: &'static mut usize = Box::leak(x); - /// *static_ref += 1; - /// assert_eq!(*static_ref, 42); + /// fn main() { + /// let x = Box::new(41); + /// let static_ref: &'static mut usize = Box::leak(x); + /// *static_ref += 1; + /// assert_eq!(*static_ref, 42); + /// } /// ``` /// /// Unsized data: /// /// ``` - /// let x = vec![1, 2, 3].into_boxed_slice(); - /// let static_ref = Box::leak(x); - /// static_ref[0] = 4; - /// assert_eq!(*static_ref, [4, 2, 3]); + /// fn main() { + /// let x = vec![1, 2, 3].into_boxed_slice(); + /// let static_ref = Box::leak(x); + /// static_ref[0] = 4; + /// assert_eq!(*static_ref, [4, 2, 3]); + /// } /// ``` #[stable(feature = "box_leak", since = "1.26.0")] #[inline] @@ -782,9 +780,11 @@ impl Box { /// } /// } /// - /// let my_string = "Hello World".to_string(); - /// print_if_string(Box::new(my_string)); - /// print_if_string(Box::new(0i8)); + /// fn main() { + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// } /// ``` pub fn downcast(self) -> Result, Box> { if self.is::() { @@ -814,9 +814,11 @@ impl Box { /// } /// } /// - /// let my_string = "Hello World".to_string(); - /// print_if_string(Box::new(my_string)); - /// print_if_string(Box::new(0i8)); + /// fn main() { + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// } /// ``` pub fn downcast(self) -> Result, Box> { >::downcast(self).map_err(|s| unsafe { @@ -881,33 +883,11 @@ impl Iterator for Box { fn nth(&mut self, n: usize) -> Option { (**self).nth(n) } - fn last(self) -> Option { - BoxIter::last(self) - } -} - -trait BoxIter { - type Item; - fn last(self) -> Option; -} - -impl BoxIter for Box { - type Item = I::Item; - default fn last(self) -> Option { - #[inline] - fn some(_: Option, x: T) -> Option { - Some(x) - } - - self.fold(None, some) - } } -/// Specialization for sized `I`s that uses `I`s implementation of `last()` -/// instead of the default. #[stable(feature = "rust1", since = "1.0.0")] -impl BoxIter for Box { - fn last(self) -> Option { +impl Iterator for Box { + fn last(self) -> Option where I: Sized { (*self).last() } } diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 83fd4485f7321..ddf012d15029a 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -2226,12 +2226,14 @@ impl<'a, K: Ord, V: Default> Entry<'a, K, V> { /// # Examples /// /// ``` + /// # fn main() { /// use std::collections::BTreeMap; /// /// let mut map: BTreeMap<&str, Option> = BTreeMap::new(); /// map.entry("poneyland").or_default(); /// /// assert_eq!(map["poneyland"], None); + /// # } /// ``` pub fn or_default(self) -> &'a mut V { match self { diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index f0796354e00c3..0cb91ba4c81da 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -2,7 +2,7 @@ // to TreeMap use core::borrow::Borrow; -use core::cmp::Ordering::{Less, Greater, Equal}; +use core::cmp::Ordering::{self, Less, Greater, Equal}; use core::cmp::{max, min}; use core::fmt::{self, Debug}; use core::iter::{Peekable, FromIterator, FusedIterator}; @@ -109,77 +109,6 @@ pub struct Range<'a, T: 'a> { iter: btree_map::Range<'a, T, ()>, } -/// Core of SymmetricDifference and Union. -/// More efficient than btree.map.MergeIter, -/// and crucially for SymmetricDifference, nexts() reports on both sides. -#[derive(Clone)] -struct MergeIterInner - where I: Iterator, - I::Item: Copy, -{ - a: I, - b: I, - peeked: Option>, -} - -#[derive(Copy, Clone, Debug)] -enum MergeIterPeeked { - A(I::Item), - B(I::Item), -} - -impl MergeIterInner - where I: ExactSizeIterator + FusedIterator, - I::Item: Copy + Ord, -{ - fn new(a: I, b: I) -> Self { - MergeIterInner { a, b, peeked: None } - } - - fn nexts(&mut self) -> (Option, Option) { - let mut a_next = match self.peeked { - Some(MergeIterPeeked::A(next)) => Some(next), - _ => self.a.next(), - }; - let mut b_next = match self.peeked { - Some(MergeIterPeeked::B(next)) => Some(next), - _ => self.b.next(), - }; - let ord = match (a_next, b_next) { - (None, None) => Equal, - (_, None) => Less, - (None, _) => Greater, - (Some(a1), Some(b1)) => a1.cmp(&b1), - }; - self.peeked = match ord { - Less => b_next.take().map(MergeIterPeeked::B), - Equal => None, - Greater => a_next.take().map(MergeIterPeeked::A), - }; - (a_next, b_next) - } - - fn lens(&self) -> (usize, usize) { - match self.peeked { - Some(MergeIterPeeked::A(_)) => (1 + self.a.len(), self.b.len()), - Some(MergeIterPeeked::B(_)) => (self.a.len(), 1 + self.b.len()), - _ => (self.a.len(), self.b.len()), - } - } -} - -impl Debug for MergeIterInner - where I: Iterator + Debug, - I::Item: Copy + Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("MergeIterInner") - .field(&self.a) - .field(&self.b) - .finish() - } -} - /// A lazy iterator producing elements in the difference of `BTreeSet`s. /// /// This `struct` is created by the [`difference`] method on [`BTreeSet`]. @@ -191,25 +120,34 @@ impl Debug for MergeIterInner pub struct Difference<'a, T: 'a> { inner: DifferenceInner<'a, T>, } -#[derive(Debug)] enum DifferenceInner<'a, T: 'a> { Stitch { - // iterate all of self and some of other, spotting matches along the way self_iter: Iter<'a, T>, other_iter: Peekable>, }, Search { - // iterate a small set, look up in the large set self_iter: Iter<'a, T>, other_set: &'a BTreeSet, }, - Iterate(Iter<'a, T>), // simply stream self's elements } #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for Difference<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Difference").field(&self.inner).finish() + match &self.inner { + DifferenceInner::Stitch { + self_iter, + other_iter, + } => f + .debug_tuple("Difference") + .field(&self_iter) + .field(&other_iter) + .finish(), + DifferenceInner::Search { + self_iter, + other_set: _, + } => f.debug_tuple("Difference").field(&self_iter).finish(), + } } } @@ -221,12 +159,18 @@ impl fmt::Debug for Difference<'_, T> { /// [`BTreeSet`]: struct.BTreeSet.html /// [`symmetric_difference`]: struct.BTreeSet.html#method.symmetric_difference #[stable(feature = "rust1", since = "1.0.0")] -pub struct SymmetricDifference<'a, T: 'a>(MergeIterInner>); +pub struct SymmetricDifference<'a, T: 'a> { + a: Peekable>, + b: Peekable>, +} #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for SymmetricDifference<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("SymmetricDifference").field(&self.0).finish() + f.debug_tuple("SymmetricDifference") + .field(&self.a) + .field(&self.b) + .finish() } } @@ -241,25 +185,34 @@ impl fmt::Debug for SymmetricDifference<'_, T> { pub struct Intersection<'a, T: 'a> { inner: IntersectionInner<'a, T>, } -#[derive(Debug)] enum IntersectionInner<'a, T: 'a> { Stitch { - // iterate similarly sized sets jointly, spotting matches along the way a: Iter<'a, T>, b: Iter<'a, T>, }, Search { - // iterate a small set, look up in the large set small_iter: Iter<'a, T>, large_set: &'a BTreeSet, }, - Answer(Option<&'a T>), // return a specific value or emptiness } #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for Intersection<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Intersection").field(&self.inner).finish() + match &self.inner { + IntersectionInner::Stitch { + a, + b, + } => f + .debug_tuple("Intersection") + .field(&a) + .field(&b) + .finish(), + IntersectionInner::Search { + small_iter, + large_set: _, + } => f.debug_tuple("Intersection").field(&small_iter).finish(), + } } } @@ -271,12 +224,18 @@ impl fmt::Debug for Intersection<'_, T> { /// [`BTreeSet`]: struct.BTreeSet.html /// [`union`]: struct.BTreeSet.html#method.union #[stable(feature = "rust1", since = "1.0.0")] -pub struct Union<'a, T: 'a>(MergeIterInner>); +pub struct Union<'a, T: 'a> { + a: Peekable>, + b: Peekable>, +} #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for Union<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Union").field(&self.0).finish() + f.debug_tuple("Union") + .field(&self.a) + .field(&self.b) + .finish() } } @@ -355,48 +314,24 @@ impl BTreeSet { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T> { - let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = - (self.iter().next(), self.iter().next_back()) - { - (self_min, self_max) - } else { - return Difference { - inner: DifferenceInner::Iterate(self.iter()), - }; - }; - let (other_min, other_max) = if let (Some(other_min), Some(other_max)) = - (other.iter().next(), other.iter().next_back()) - { - (other_min, other_max) - } else { - return Difference { - inner: DifferenceInner::Iterate(self.iter()), - }; - }; - Difference { - inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { - (Greater, _) | (_, Less) => DifferenceInner::Iterate(self.iter()), - (Equal, _) => { - let mut self_iter = self.iter(); - self_iter.next(); - DifferenceInner::Iterate(self_iter) - } - (_, Equal) => { - let mut self_iter = self.iter(); - self_iter.next_back(); - DifferenceInner::Iterate(self_iter) - } - _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { - DifferenceInner::Search { - self_iter: self.iter(), - other_set: other, - } - } - _ => DifferenceInner::Stitch { + if self.len() > other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { + // Self is bigger than or not much smaller than other set. + // Iterate both sets jointly, spotting matches along the way. + Difference { + inner: DifferenceInner::Stitch { self_iter: self.iter(), other_iter: other.iter().peekable(), }, - }, + } + } else { + // Self is much smaller than other set, or both sets are empty. + // Iterate the small set, searching for matches in the large set. + Difference { + inner: DifferenceInner::Search { + self_iter: self.iter(), + other_set: other, + }, + } } } @@ -424,7 +359,10 @@ impl BTreeSet { pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet) -> SymmetricDifference<'a, T> { - SymmetricDifference(MergeIterInner::new(self.iter(), other.iter())) + SymmetricDifference { + a: self.iter().peekable(), + b: other.iter().peekable(), + } } /// Visits the values representing the intersection, @@ -449,46 +387,29 @@ impl BTreeSet { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn intersection<'a>(&'a self, other: &'a BTreeSet) -> Intersection<'a, T> { - let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = - (self.iter().next(), self.iter().next_back()) - { - (self_min, self_max) + let (small, other) = if self.len() <= other.len() { + (self, other) } else { - return Intersection { - inner: IntersectionInner::Answer(None), - }; + (other, self) }; - let (other_min, other_max) = if let (Some(other_min), Some(other_max)) = - (other.iter().next(), other.iter().next_back()) - { - (other_min, other_max) - } else { - return Intersection { - inner: IntersectionInner::Answer(None), - }; - }; - Intersection { - inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { - (Greater, _) | (_, Less) => IntersectionInner::Answer(None), - (Equal, _) => IntersectionInner::Answer(Some(self_min)), - (_, Equal) => IntersectionInner::Answer(Some(self_max)), - _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { - IntersectionInner::Search { - small_iter: self.iter(), - large_set: other, - } - } - _ if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { - IntersectionInner::Search { - small_iter: other.iter(), - large_set: self, - } - } - _ => IntersectionInner::Stitch { - a: self.iter(), + if small.len() > other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { + // Small set is not much smaller than other set. + // Iterate both sets jointly, spotting matches along the way. + Intersection { + inner: IntersectionInner::Stitch { + a: small.iter(), b: other.iter(), }, - }, + } + } else { + // Big difference in number of elements, or both sets are empty. + // Iterate the small set, searching for matches in the large set. + Intersection { + inner: IntersectionInner::Search { + small_iter: small.iter(), + large_set: other, + }, + } } } @@ -512,7 +433,10 @@ impl BTreeSet { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn union<'a>(&'a self, other: &'a BTreeSet) -> Union<'a, T> { - Union(MergeIterInner::new(self.iter(), other.iter())) + Union { + a: self.iter().peekable(), + b: other.iter().peekable(), + } } /// Clears the set, removing all values. @@ -620,61 +544,43 @@ impl BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] pub fn is_subset(&self, other: &BTreeSet) -> bool { // Same result as self.difference(other).next().is_none() - // but the code below is faster (hugely in some cases). + // but the 3 paths below are faster (in order: hugely, 20%, 5%). if self.len() > other.len() { - return false; - } - let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = - (self.iter().next(), self.iter().next_back()) - { - (self_min, self_max) - } else { - return true; // self is empty - }; - let (other_min, other_max) = if let (Some(other_min), Some(other_max)) = - (other.iter().next(), other.iter().next_back()) - { - (other_min, other_max) - } else { - return false; // other is empty - }; - let mut self_iter = self.iter(); - match self_min.cmp(other_min) { - Less => return false, - Equal => { - self_iter.next(); - } - Greater => (), - } - match self_max.cmp(other_max) { - Greater => return false, - Equal => { - self_iter.next_back(); - } - Less => (), - } - if self_iter.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { - // Big difference in number of elements. - for next in self_iter { - if !other.contains(next) { + false + } else if self.len() > other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { + // Self is not much smaller than other set. + // Stolen from TreeMap + let mut x = self.iter(); + let mut y = other.iter(); + let mut a = x.next(); + let mut b = y.next(); + while a.is_some() { + if b.is_none() { return false; } + + let a1 = a.unwrap(); + let b1 = b.unwrap(); + + match b1.cmp(a1) { + Less => (), + Greater => return false, + Equal => a = x.next(), + } + + b = y.next(); } + true } else { - // Self is not much smaller than other set. - let mut other_iter = other.iter(); - other_iter.next(); - other_iter.next_back(); - let mut self_next = self_iter.next(); - while let Some(self1) = self_next { - match other_iter.next().map_or(Less, |other1| self1.cmp(other1)) { - Less => return false, - Equal => self_next = self_iter.next(), - Greater => (), + // Big difference in number of elements, or both sets are empty. + // Iterate the small set, searching for matches in the large set. + for next in self { + if !other.contains(next) { + return false; } } + true } - true } /// Returns `true` if the set is a superset of another, @@ -1186,6 +1092,15 @@ impl<'a, T> DoubleEndedIterator for Range<'a, T> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Range<'_, T> {} +/// Compares `x` and `y`, but return `short` if x is None and `long` if y is None +fn cmp_opt(x: Option<&T>, y: Option<&T>, short: Ordering, long: Ordering) -> Ordering { + match (x, y) { + (None, _) => short, + (_, None) => long, + (Some(x1), Some(y1)) => x1.cmp(y1), + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Difference<'_, T> { fn clone(&self) -> Self { @@ -1205,7 +1120,6 @@ impl Clone for Difference<'_, T> { self_iter: self_iter.clone(), other_set, }, - DifferenceInner::Iterate(iter) => DifferenceInner::Iterate(iter.clone()), }, } } @@ -1224,7 +1138,7 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> { loop { match other_iter .peek() - .map_or(Less, |other_next| self_next.cmp(other_next)) + .map_or(Less, |other_next| Ord::cmp(self_next, other_next)) { Less => return Some(self_next), Equal => { @@ -1246,7 +1160,6 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> { return Some(self_next); } }, - DifferenceInner::Iterate(iter) => iter.next(), } } @@ -1254,13 +1167,12 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> { let (self_len, other_len) = match &self.inner { DifferenceInner::Stitch { self_iter, - other_iter, + other_iter } => (self_iter.len(), other_iter.len()), DifferenceInner::Search { self_iter, - other_set, + other_set } => (self_iter.len(), other_set.len()), - DifferenceInner::Iterate(iter) => (iter.len(), 0), }; (self_len.saturating_sub(other_len), Some(self_len)) } @@ -1272,7 +1184,10 @@ impl FusedIterator for Difference<'_, T> {} #[stable(feature = "rust1", since = "1.0.0")] impl Clone for SymmetricDifference<'_, T> { fn clone(&self) -> Self { - SymmetricDifference(self.0.clone()) + SymmetricDifference { + a: self.a.clone(), + b: self.b.clone(), + } } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1281,19 +1196,19 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> { fn next(&mut self) -> Option<&'a T> { loop { - let (a_next, b_next) = self.0.nexts(); - if a_next.and(b_next).is_none() { - return a_next.or(b_next); + match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { + Less => return self.a.next(), + Equal => { + self.a.next(); + self.b.next(); + } + Greater => return self.b.next(), } } } fn size_hint(&self) -> (usize, Option) { - let (a_len, b_len) = self.0.lens(); - // No checked_add, because even if a and b refer to the same set, - // and T is an empty type, the storage overhead of sets limits - // the number of elements to less than half the range of usize. - (0, Some(a_len + b_len)) + (0, Some(self.a.len() + self.b.len())) } } @@ -1319,7 +1234,6 @@ impl Clone for Intersection<'_, T> { small_iter: small_iter.clone(), large_set, }, - IntersectionInner::Answer(answer) => IntersectionInner::Answer(*answer), }, } } @@ -1337,7 +1251,7 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> { let mut a_next = a.next()?; let mut b_next = b.next()?; loop { - match a_next.cmp(b_next) { + match Ord::cmp(a_next, b_next) { Less => a_next = a.next()?, Greater => b_next = b.next()?, Equal => return Some(a_next), @@ -1353,17 +1267,15 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> { return Some(small_next); } }, - IntersectionInner::Answer(answer) => answer.take(), } } fn size_hint(&self) -> (usize, Option) { - match &self.inner { - IntersectionInner::Stitch { a, b } => (0, Some(min(a.len(), b.len()))), - IntersectionInner::Search { small_iter, .. } => (0, Some(small_iter.len())), - IntersectionInner::Answer(None) => (0, Some(0)), - IntersectionInner::Answer(Some(_)) => (1, Some(1)), - } + let min_len = match &self.inner { + IntersectionInner::Stitch { a, b } => min(a.len(), b.len()), + IntersectionInner::Search { small_iter, .. } => small_iter.len(), + }; + (0, Some(min_len)) } } @@ -1373,7 +1285,10 @@ impl FusedIterator for Intersection<'_, T> {} #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Union<'_, T> { fn clone(&self) -> Self { - Union(self.0.clone()) + Union { + a: self.a.clone(), + b: self.b.clone(), + } } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1381,13 +1296,19 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { type Item = &'a T; fn next(&mut self) -> Option<&'a T> { - let (a_next, b_next) = self.0.nexts(); - a_next.or(b_next) + match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { + Less => self.a.next(), + Equal => { + self.b.next(); + self.a.next() + } + Greater => self.b.next(), + } } fn size_hint(&self) -> (usize, Option) { - let (a_len, b_len) = self.0.lens(); - // No checked_add - see SymmetricDifference::size_hint. + let a_len = self.a.len(); + let b_len = self.b.len(); (max(a_len, b_len), Some(a_len + b_len)) } } diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index 702df250999fb..816a71f255798 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -1197,19 +1197,6 @@ impl Clone for LinkedList { fn clone(&self) -> Self { self.iter().cloned().collect() } - - fn clone_from(&mut self, other: &Self) { - let mut iter_other = other.iter(); - if self.len() > other.len() { - self.split_off(other.len()); - } - for (elem, elem_other) in self.iter_mut().zip(&mut iter_other) { - elem.clone_from(elem_other); - } - if !iter_other.is_empty() { - self.extend(iter_other.cloned()); - } - } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/collections/linked_list/tests.rs b/src/liballoc/collections/linked_list/tests.rs index 1001f6bba3b82..ecb5948f11b36 100644 --- a/src/liballoc/collections/linked_list/tests.rs +++ b/src/liballoc/collections/linked_list/tests.rs @@ -110,49 +110,6 @@ fn test_append() { check_links(&n); } -#[test] -fn test_clone_from() { - // Short cloned from long - { - let v = vec![1, 2, 3, 4, 5]; - let u = vec![8, 7, 6, 2, 3, 4, 5]; - let mut m = list_from(&v); - let n = list_from(&u); - m.clone_from(&n); - check_links(&m); - assert_eq!(m, n); - for elt in u { - assert_eq!(m.pop_front(), Some(elt)) - } - } - // Long cloned from short - { - let v = vec![1, 2, 3, 4, 5]; - let u = vec![6, 7, 8]; - let mut m = list_from(&v); - let n = list_from(&u); - m.clone_from(&n); - check_links(&m); - assert_eq!(m, n); - for elt in u { - assert_eq!(m.pop_front(), Some(elt)) - } - } - // Two equal length lists - { - let v = vec![1, 2, 3, 4, 5]; - let u = vec![9, 8, 1, 2, 3]; - let mut m = list_from(&v); - let n = list_from(&u); - m.clone_from(&n); - check_links(&m); - assert_eq!(m, n); - for elt in u { - assert_eq!(m.pop_front(), Some(elt)) - } - } -} - #[test] fn test_insert_prev() { let mut m = list_from(&[0, 2, 4, 6, 8]); diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 8f3dfabd8886d..a4a0fbb194dd4 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -10,8 +10,8 @@ use core::array::LengthAtMost32; use core::cmp::{self, Ordering}; use core::fmt; -use core::iter::{once, repeat_with, FromIterator, FusedIterator}; -use core::mem::{self, replace}; +use core::iter::{repeat_with, FromIterator, FusedIterator}; +use core::mem; use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{Index, IndexMut, RangeBounds, Try}; use core::ptr::{self, NonNull}; @@ -57,88 +57,11 @@ pub struct VecDeque { buf: RawVec, } -/// PairSlices pairs up equal length slice parts of two deques -/// -/// For example, given deques "A" and "B" with the following division into slices: -/// -/// A: [0 1 2] [3 4 5] -/// B: [a b] [c d e] -/// -/// It produces the following sequence of matching slices: -/// -/// ([0 1], [a b]) -/// ([2], [c]) -/// ([3 4], [d e]) -/// -/// and the uneven remainder of either A or B is skipped. -struct PairSlices<'a, 'b, T> { - a0: &'a mut [T], - a1: &'a mut [T], - b0: &'b [T], - b1: &'b [T], -} - -impl<'a, 'b, T> PairSlices<'a, 'b, T> { - fn from(to: &'a mut VecDeque, from: &'b VecDeque) -> Self { - let (a0, a1) = to.as_mut_slices(); - let (b0, b1) = from.as_slices(); - PairSlices { a0, a1, b0, b1 } - } - - fn has_remainder(&self) -> bool { - !self.b0.is_empty() - } - - fn remainder(self) -> impl Iterator { - once(self.b0).chain(once(self.b1)) - } -} - -impl<'a, 'b, T> Iterator for PairSlices<'a, 'b, T> -{ - type Item = (&'a mut [T], &'b [T]); - fn next(&mut self) -> Option { - // Get next part length - let part = cmp::min(self.a0.len(), self.b0.len()); - if part == 0 { - return None; - } - let (p0, p1) = replace(&mut self.a0, &mut []).split_at_mut(part); - let (q0, q1) = self.b0.split_at(part); - - // Move a1 into a0, if it's empty (and b1, b0 the same way). - self.a0 = p1; - self.b0 = q1; - if self.a0.is_empty() { - self.a0 = replace(&mut self.a1, &mut []); - } - if self.b0.is_empty() { - self.b0 = replace(&mut self.b1, &[]); - } - Some((p0, q0)) - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Clone for VecDeque { fn clone(&self) -> VecDeque { self.iter().cloned().collect() } - - fn clone_from(&mut self, other: &Self) { - self.truncate(other.len()); - - let mut iter = PairSlices::from(self, other); - while let Some((dst, src)) = iter.next() { - dst.clone_from_slice(&src); - } - - if iter.has_remainder() { - for remainder in iter.remainder() { - self.extend(remainder.iter().cloned()); - } - } - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1817,7 +1740,7 @@ impl VecDeque { } } - elem + return elem; } /// Splits the `VecDeque` into two at the given index. @@ -2286,16 +2209,6 @@ impl<'a, T> Iterator for Iter<'a, T> { final_res } - fn nth(&mut self, n: usize) -> Option { - if n >= count(self.tail, self.head, self.ring.len()) { - self.tail = self.head; - None - } else { - self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len()); - self.next() - } - } - #[inline] fn last(mut self) -> Option<&'a T> { self.next_back() @@ -2414,16 +2327,6 @@ impl<'a, T> Iterator for IterMut<'a, T> { back.iter_mut().fold(accum, &mut f) } - fn nth(&mut self, n: usize) -> Option { - if n >= count(self.tail, self.head, self.ring.len()) { - self.tail = self.head; - None - } else { - self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len()); - self.next() - } - } - #[inline] fn last(mut self) -> Option<&'a mut T> { self.next_back() diff --git a/src/liballoc/collections/vec_deque/tests.rs b/src/liballoc/collections/vec_deque/tests.rs index d578ee0dac493..d25352399796e 100644 --- a/src/liballoc/collections/vec_deque/tests.rs +++ b/src/liballoc/collections/vec_deque/tests.rs @@ -361,29 +361,6 @@ fn test_vec_from_vecdeque() { } } -#[test] -fn test_clone_from() { - let m = vec![1; 8]; - let n = vec![2; 12]; - for pfv in 0..8 { - for pfu in 0..8 { - for longer in 0..2 { - let (vr, ur) = if longer == 0 { (&m, &n) } else { (&n, &m) }; - let mut v = VecDeque::from(vr.clone()); - for _ in 0..pfv { - v.push_front(1); - } - let mut u = VecDeque::from(ur.clone()); - for _ in 0..pfu { - u.push_front(2); - } - v.clone_from(&u); - assert_eq!(&v, &u); - } - } - } -} - #[test] fn issue_53529() { use crate::boxed::Box; diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index cbfc55233a1e0..68cbc366d7bc2 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -80,210 +80,24 @@ //! arguments which have names. Like with positional parameters, it is not //! valid to provide named parameters that are unused by the format string. //! -//! # Formatting Parameters -//! -//! Each argument being formatted can be transformed by a number of formatting -//! parameters (corresponding to `format_spec` in the syntax above). These -//! parameters affect the string representation of what's being formatted. -//! -//! ## Width -//! -//! ``` -//! // All of these print "Hello x !" -//! println!("Hello {:5}!", "x"); -//! println!("Hello {:1$}!", "x", 5); -//! println!("Hello {1:0$}!", 5, "x"); -//! println!("Hello {:width$}!", "x", width = 5); -//! ``` -//! -//! This is a parameter for the "minimum width" that the format should take up. -//! If the value's string does not fill up this many characters, then the -//! padding specified by fill/alignment will be used to take up the required -//! space (see below). -//! -//! The value for the width can also be provided as a [`usize`] in the list of -//! parameters by adding a postfix `$`, indicating that the second argument is -//! a [`usize`] specifying the width. -//! -//! Referring to an argument with the dollar syntax does not affect the "next -//! argument" counter, so it's usually a good idea to refer to arguments by -//! position, or use named arguments. -//! -//! ## Fill/Alignment -//! -//! ``` -//! assert_eq!(format!("Hello {:<5}!", "x"), "Hello x !"); -//! assert_eq!(format!("Hello {:-<5}!", "x"), "Hello x----!"); -//! assert_eq!(format!("Hello {:^5}!", "x"), "Hello x !"); -//! assert_eq!(format!("Hello {:>5}!", "x"), "Hello x!"); -//! ``` -//! -//! The optional fill character and alignment is provided normally in conjunction with the -//! [`width`](#width) parameter. It must be defined before `width`, right after the `:`. -//! This indicates that if the value being formatted is smaller than -//! `width` some extra characters will be printed around it. -//! Filling comes in the following variants for different alignments: -//! -//! * `[fill]<` - the argument is left-aligned in `width` columns -//! * `[fill]^` - the argument is center-aligned in `width` columns -//! * `[fill]>` - the argument is right-aligned in `width` columns -//! -//! The default [fill/alignment](#fillalignment) for non-numerics is a space and -//! left-aligned. The -//! defaults for numeric formatters is also a space but with right-alignment. If -//! the `0` flag (see below) is specified for numerics, then the implicit fill character is -//! `0`. -//! -//! Note that alignment may not be implemented by some types. In particular, it -//! is not generally implemented for the `Debug` trait. A good way to ensure -//! padding is applied is to format your input, then pad this resulting string -//! to obtain your output: -//! -//! ``` -//! println!("Hello {:^15}!", format!("{:?}", Some("hi"))); // => "Hello Some("hi") !" -//! ``` -//! -//! ## Sign/`#`/`0` -//! -//! ``` -//! assert_eq!(format!("Hello {:+}!", 5), "Hello +5!"); -//! assert_eq!(format!("{:#x}!", 27), "0x1b!"); -//! assert_eq!(format!("Hello {:05}!", 5), "Hello 00005!"); -//! assert_eq!(format!("Hello {:05}!", -5), "Hello -0005!"); -//! assert_eq!(format!("{:#010x}!", 27), "0x0000001b!"); -//! ``` -//! -//! These are all flags altering the behavior of the formatter. -//! -//! * `+` - This is intended for numeric types and indicates that the sign -//! should always be printed. Positive signs are never printed by -//! default, and the negative sign is only printed by default for the -//! `Signed` trait. This flag indicates that the correct sign (`+` or `-`) -//! should always be printed. -//! * `-` - Currently not used -//! * `#` - This flag is indicates that the "alternate" form of printing should -//! be used. The alternate forms are: -//! * `#?` - pretty-print the [`Debug`] formatting -//! * `#x` - precedes the argument with a `0x` -//! * `#X` - precedes the argument with a `0x` -//! * `#b` - precedes the argument with a `0b` -//! * `#o` - precedes the argument with a `0o` -//! * `0` - This is used to indicate for integer formats that the padding to `width` should -//! both be done with a `0` character as well as be sign-aware. A format -//! like `{:08}` would yield `00000001` for the integer `1`, while the -//! same format would yield `-0000001` for the integer `-1`. Notice that -//! the negative version has one fewer zero than the positive version. -//! Note that padding zeroes are always placed after the sign (if any) -//! and before the digits. When used together with the `#` flag, a similar -//! rule applies: padding zeroes are inserted after the prefix but before -//! the digits. The prefix is included in the total width. -//! -//! ## Precision -//! -//! For non-numeric types, this can be considered a "maximum width". If the resulting string is -//! longer than this width, then it is truncated down to this many characters and that truncated -//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set. -//! -//! For integral types, this is ignored. -//! -//! For floating-point types, this indicates how many digits after the decimal point should be -//! printed. -//! -//! There are three possible ways to specify the desired `precision`: -//! -//! 1. An integer `.N`: -//! -//! the integer `N` itself is the precision. -//! -//! 2. An integer or name followed by dollar sign `.N$`: -//! -//! use format *argument* `N` (which must be a `usize`) as the precision. -//! -//! 3. An asterisk `.*`: -//! -//! `.*` means that this `{...}` is associated with *two* format inputs rather than one: the -//! first input holds the `usize` precision, and the second holds the value to print. Note that -//! in this case, if one uses the format string `{:.*}`, then the `` part refers -//! to the *value* to print, and the `precision` must come in the input preceding ``. -//! -//! For example, the following calls all print the same thing `Hello x is 0.01000`: -//! -//! ``` -//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)} -//! println!("Hello {0} is {1:.5}", "x", 0.01); -//! -//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)} -//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01); -//! -//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)} -//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01); -//! -//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision -//! // specified in first of next two args (5)} -//! println!("Hello {} is {:.*}", "x", 5, 0.01); -//! -//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision -//! // specified in its predecessor (5)} -//! println!("Hello {} is {2:.*}", "x", 5, 0.01); -//! -//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified -//! // in arg "prec" (5)} -//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01); -//! ``` +//! ## Argument types //! -//! While these: +//! Each argument's type is dictated by the format string. +//! There are various parameters which require a particular type, however. +//! An example is the `{:.*}` syntax, which sets the number of decimal places +//! in floating-point types: //! //! ``` -//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56); -//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56"); -//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56"); -//! ``` +//! let formatted_number = format!("{:.*}", 2, 1.234567); //! -//! print two significantly different things: -//! -//! ```text -//! Hello, `1234.560` has 3 fractional digits -//! Hello, `123` has 3 characters -//! Hello, ` 123` has 3 right-aligned characters +//! assert_eq!("1.23", formatted_number) //! ``` //! -//! # Escaping -//! -//! The literal characters `{` and `}` may be included in a string by preceding -//! them with the same character. For example, the `{` character is escaped with -//! `{{` and the `}` character is escaped with `}}`. +//! If this syntax is used, then the number of characters to print precedes the +//! actual object being formatted, and the number of characters must have the +//! type [`usize`]. //! -//! ``` -//! assert_eq!(format!("Hello {{}}"), "Hello {}"); -//! assert_eq!(format!("{{ Hello"), "{ Hello"); -//! ``` -//! -//! # Syntax -//! -//! To summarize, here you can find the full grammar of format strings. -//! The syntax for the formatting language used is drawn from other languages, -//! so it should not be too alien. Arguments are formatted with Python-like -//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like -//! `%`. The actual grammar for the formatting syntax is: -//! -//! ```text -//! format_string := [ maybe-format ] * -//! maybe-format := '{' '{' | '}' '}' | -//! format := '{' [ argument ] [ ':' format_spec ] '}' -//! argument := integer | identifier -//! -//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type] -//! fill := character -//! align := '<' | '^' | '>' -//! sign := '+' | '-' -//! width := count -//! precision := count | '*' -//! type := identifier | '?' | '' -//! count := parameter | integer -//! parameter := argument '$' -//! ``` -//! -//! # Formatting traits +//! ## Formatting traits //! //! When requesting that an argument be formatted with a particular type, you //! are actually requesting that an argument ascribes to a particular trait. @@ -406,7 +220,7 @@ //! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\""); //! ``` //! -//! # Related macros +//! ## Related macros //! //! There are a number of related macros in the [`format!`] family. The ones that //! are currently implemented are: @@ -486,6 +300,185 @@ //! it would internally pass around this structure until it has been determined //! where output should go to. //! +//! # Syntax +//! +//! The syntax for the formatting language used is drawn from other languages, +//! so it should not be too alien. Arguments are formatted with Python-like +//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like +//! `%`. The actual grammar for the formatting syntax is: +//! +//! ```text +//! format_string := [ maybe-format ] * +//! maybe-format := '{' '{' | '}' '}' | +//! format := '{' [ argument ] [ ':' format_spec ] '}' +//! argument := integer | identifier +//! +//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type] +//! fill := character +//! align := '<' | '^' | '>' +//! sign := '+' | '-' +//! width := count +//! precision := count | '*' +//! type := identifier | '?' | '' +//! count := parameter | integer +//! parameter := argument '$' +//! ``` +//! +//! # Formatting Parameters +//! +//! Each argument being formatted can be transformed by a number of formatting +//! parameters (corresponding to `format_spec` in the syntax above). These +//! parameters affect the string representation of what's being formatted. +//! +//! ## Fill/Alignment +//! +//! The fill character is provided normally in conjunction with the +//! [`width`](#width) +//! parameter. This indicates that if the value being formatted is smaller than +//! `width` some extra characters will be printed around it. The extra +//! characters are specified by `fill`, and the alignment can be one of the +//! following options: +//! +//! * `<` - the argument is left-aligned in `width` columns +//! * `^` - the argument is center-aligned in `width` columns +//! * `>` - the argument is right-aligned in `width` columns +//! +//! Note that alignment may not be implemented by some types. In particular, it +//! is not generally implemented for the `Debug` trait. A good way to ensure +//! padding is applied is to format your input, then use this resulting string +//! to pad your output. +//! +//! ## Sign/`#`/`0` +//! +//! These can all be interpreted as flags for a particular formatter. +//! +//! * `+` - This is intended for numeric types and indicates that the sign +//! should always be printed. Positive signs are never printed by +//! default, and the negative sign is only printed by default for the +//! `Signed` trait. This flag indicates that the correct sign (`+` or `-`) +//! should always be printed. +//! * `-` - Currently not used +//! * `#` - This flag is indicates that the "alternate" form of printing should +//! be used. The alternate forms are: +//! * `#?` - pretty-print the [`Debug`] formatting +//! * `#x` - precedes the argument with a `0x` +//! * `#X` - precedes the argument with a `0x` +//! * `#b` - precedes the argument with a `0b` +//! * `#o` - precedes the argument with a `0o` +//! * `0` - This is used to indicate for integer formats that the padding should +//! both be done with a `0` character as well as be sign-aware. A format +//! like `{:08}` would yield `00000001` for the integer `1`, while the +//! same format would yield `-0000001` for the integer `-1`. Notice that +//! the negative version has one fewer zero than the positive version. +//! Note that padding zeroes are always placed after the sign (if any) +//! and before the digits. When used together with the `#` flag, a similar +//! rule applies: padding zeroes are inserted after the prefix but before +//! the digits. +//! +//! ## Width +//! +//! This is a parameter for the "minimum width" that the format should take up. +//! If the value's string does not fill up this many characters, then the +//! padding specified by fill/alignment will be used to take up the required +//! space. +//! +//! The default [fill/alignment](#fillalignment) for non-numerics is a space and +//! left-aligned. The +//! defaults for numeric formatters is also a space but with right-alignment. If +//! the `0` flag is specified for numerics, then the implicit fill character is +//! `0`. +//! +//! The value for the width can also be provided as a [`usize`] in the list of +//! parameters by using the dollar syntax indicating that the second argument is +//! a [`usize`] specifying the width, for example: +//! +//! ``` +//! // All of these print "Hello x !" +//! println!("Hello {:5}!", "x"); +//! println!("Hello {:1$}!", "x", 5); +//! println!("Hello {1:0$}!", 5, "x"); +//! println!("Hello {:width$}!", "x", width = 5); +//! ``` +//! +//! Referring to an argument with the dollar syntax does not affect the "next +//! argument" counter, so it's usually a good idea to refer to arguments by +//! position, or use named arguments. +//! +//! ## Precision +//! +//! For non-numeric types, this can be considered a "maximum width". If the resulting string is +//! longer than this width, then it is truncated down to this many characters and that truncated +//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set. +//! +//! For integral types, this is ignored. +//! +//! For floating-point types, this indicates how many digits after the decimal point should be +//! printed. +//! +//! There are three possible ways to specify the desired `precision`: +//! +//! 1. An integer `.N`: +//! +//! the integer `N` itself is the precision. +//! +//! 2. An integer or name followed by dollar sign `.N$`: +//! +//! use format *argument* `N` (which must be a `usize`) as the precision. +//! +//! 3. An asterisk `.*`: +//! +//! `.*` means that this `{...}` is associated with *two* format inputs rather than one: the +//! first input holds the `usize` precision, and the second holds the value to print. Note that +//! in this case, if one uses the format string `{:.*}`, then the `` part refers +//! to the *value* to print, and the `precision` must come in the input preceding ``. +//! +//! For example, the following calls all print the same thing `Hello x is 0.01000`: +//! +//! ``` +//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)} +//! println!("Hello {0} is {1:.5}", "x", 0.01); +//! +//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)} +//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01); +//! +//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)} +//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01); +//! +//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision +//! // specified in first of next two args (5)} +//! println!("Hello {} is {:.*}", "x", 5, 0.01); +//! +//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision +//! // specified in its predecessor (5)} +//! println!("Hello {} is {2:.*}", "x", 5, 0.01); +//! +//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified +//! // in arg "prec" (5)} +//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01); +//! ``` +//! +//! While these: +//! +//! ``` +//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56); +//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56"); +//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56"); +//! ``` +//! +//! print two significantly different things: +//! +//! ```text +//! Hello, `1234.560` has 3 fractional digits +//! Hello, `123` has 3 characters +//! Hello, ` 123` has 3 right-aligned characters +//! ``` +//! +//! # Escaping +//! +//! The literal characters `{` and `}` may be included in a string by preceding +//! them with the same character. For example, the `{` character is escaped with +//! `{{` and the `}` character is escaped with `}}`. +//! //! [`usize`]: ../../std/primitive.usize.html //! [`isize`]: ../../std/primitive.isize.html //! [`i8`]: ../../std/primitive.i8.html diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 94379afc2bd45..247cd9a020161 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -85,7 +85,6 @@ #![feature(const_generic_impls_guard)] #![feature(const_generics)] #![feature(const_in_array_repeat_expressions)] -#![feature(cow_is_borrowed)] #![feature(dispatch_from_dyn)] #![feature(core_intrinsics)] #![feature(container_error_extra)] @@ -122,6 +121,7 @@ #![feature(maybe_uninit_extra, maybe_uninit_slice)] #![feature(alloc_layout_extra)] #![feature(try_trait)] +#![feature(mem_take)] #![feature(associated_type_bounds)] // Allow testing this library @@ -154,7 +154,7 @@ mod boxed { #[cfg(test)] mod tests; pub mod collections; -#[cfg(target_has_atomic = "ptr")] +#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))] pub mod sync; pub mod rc; pub mod raw_vec; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index f1c4c32e116ea..f234ac5ebe51b 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -3,9 +3,8 @@ //! //! The type [`Rc`][`Rc`] provides shared ownership of a value of type `T`, //! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new -//! pointer to the same allocation in the heap. When the last [`Rc`] pointer to a -//! given allocation is destroyed, the value stored in that allocation (often -//! referred to as "inner value") is also dropped. +//! pointer to the same value in the heap. When the last [`Rc`] pointer to a +//! given value is destroyed, the pointed-to value is also destroyed. //! //! Shared references in Rust disallow mutation by default, and [`Rc`] //! is no exception: you cannot generally obtain a mutable reference to @@ -22,10 +21,8 @@ //! //! The [`downgrade`][downgrade] method can be used to create a non-owning //! [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d -//! to an [`Rc`], but this will return [`None`] if the value stored in the allocation has -//! already been dropped. In other words, `Weak` pointers do not keep the value -//! inside the allocation alive; however, they *do* keep the allocation -//! (the backing store for the inner value) alive. +//! to an [`Rc`], but this will return [`None`] if the value has +//! already been dropped. //! //! A cycle between [`Rc`] pointers will never be deallocated. For this reason, //! [`Weak`] is used to break cycles. For example, a tree could have strong @@ -44,13 +41,13 @@ //! Rc::downgrade(&my_rc); //! ``` //! -//! [`Weak`][`Weak`] does not auto-dereference to `T`, because the inner value may have -//! already been dropped. +//! [`Weak`][`Weak`] does not auto-dereference to `T`, because the value may have +//! already been destroyed. //! //! # Cloning references //! -//! Creating a new reference to the same allocation as an existing reference counted pointer -//! is done using the `Clone` trait implemented for [`Rc`][`Rc`] and [`Weak`][`Weak`]. +//! Creating a new reference from an existing reference counted pointer is done using the +//! `Clone` trait implemented for [`Rc`][`Rc`] and [`Weak`][`Weak`]. //! //! ``` //! use std::rc::Rc; @@ -96,7 +93,7 @@ //! ); //! //! // Create `Gadget`s belonging to `gadget_owner`. Cloning the `Rc` -//! // gives us a new pointer to the same `Owner` allocation, incrementing +//! // value gives us a new pointer to the same `Owner` value, incrementing //! // the reference count in the process. //! let gadget1 = Gadget { //! id: 1, @@ -113,8 +110,8 @@ //! // Despite dropping `gadget_owner`, we're still able to print out the name //! // of the `Owner` of the `Gadget`s. This is because we've only dropped a //! // single `Rc`, not the `Owner` it points to. As long as there are -//! // other `Rc` pointing at the same `Owner` allocation, it will remain -//! // live. The field projection `gadget1.owner.name` works because +//! // other `Rc` values pointing at the same `Owner`, it will remain +//! // allocated. The field projection `gadget1.owner.name` works because //! // `Rc` automatically dereferences to `Owner`. //! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name); //! println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name); @@ -127,9 +124,9 @@ //! //! If our requirements change, and we also need to be able to traverse from //! `Owner` to `Gadget`, we will run into problems. An [`Rc`] pointer from `Owner` -//! to `Gadget` introduces a cycle. This means that their -//! reference counts can never reach 0, and the allocation will never be destroyed: -//! a memory leak. In order to get around this, we can use [`Weak`] +//! to `Gadget` introduces a cycle between the values. This means that their +//! reference counts can never reach 0, and the values will remain allocated +//! forever: a memory leak. In order to get around this, we can use [`Weak`] //! pointers. //! //! Rust actually makes it somewhat difficult to produce this loop in the first @@ -196,10 +193,10 @@ //! for gadget_weak in gadget_owner.gadgets.borrow().iter() { //! //! // `gadget_weak` is a `Weak`. Since `Weak` pointers can't -//! // guarantee the allocation still exists, we need to call +//! // guarantee the value is still allocated, we need to call //! // `upgrade`, which returns an `Option>`. //! // -//! // In this case we know the allocation still exists, so we simply +//! // In this case we know the value still exists, so we simply //! // `unwrap` the `Option`. In a more complicated program, you might //! // need graceful error handling for a `None` result. //! @@ -368,7 +365,7 @@ impl Rc { unsafe { Pin::new_unchecked(Rc::new(value)) } } - /// Returns the inner value, if the `Rc` has exactly one strong reference. + /// Returns the contained value, if the `Rc` has exactly one strong reference. /// /// Otherwise, an [`Err`][result] is returned with the same `Rc` that was /// passed in. @@ -449,7 +446,7 @@ impl Rc> { /// # Safety /// /// As with [`MaybeUninit::assume_init`], - /// it is up to the caller to guarantee that the inner value + /// 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. @@ -488,7 +485,7 @@ impl Rc<[mem::MaybeUninit]> { /// # Safety /// /// As with [`MaybeUninit::assume_init`], - /// it is up to the caller to guarantee that the inner value + /// 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. @@ -607,7 +604,7 @@ impl Rc { unsafe { NonNull::new_unchecked(Rc::into_raw(this) as *mut _) } } - /// Creates a new [`Weak`][weak] pointer to this allocation. + /// Creates a new [`Weak`][weak] pointer to this value. /// /// [weak]: struct.Weak.html /// @@ -628,7 +625,7 @@ impl Rc { Weak { ptr: this.ptr } } - /// Gets the number of [`Weak`][weak] pointers to this allocation. + /// Gets the number of [`Weak`][weak] pointers to this value. /// /// [weak]: struct.Weak.html /// @@ -648,7 +645,7 @@ impl Rc { this.weak() - 1 } - /// Gets the number of strong (`Rc`) pointers to this allocation. + /// Gets the number of strong (`Rc`) pointers to this value. /// /// # Examples /// @@ -667,7 +664,7 @@ impl Rc { } /// Returns `true` if there are no other `Rc` or [`Weak`][weak] pointers to - /// this allocation. + /// this inner value. /// /// [weak]: struct.Weak.html #[inline] @@ -675,14 +672,14 @@ impl Rc { Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1 } - /// Returns a mutable reference into the given `Rc`, if there are - /// no other `Rc` or [`Weak`][weak] pointers to the same allocation. + /// Returns a mutable reference to the inner value, if there are + /// no other `Rc` or [`Weak`][weak] pointers to the same value. /// /// Returns [`None`] otherwise, because it is not safe to /// mutate a shared value. /// /// See also [`make_mut`][make_mut], which will [`clone`][clone] - /// the inner value when there are other pointers. + /// the inner value when it's shared. /// /// [weak]: struct.Weak.html /// [`None`]: ../../std/option/enum.Option.html#variant.None @@ -713,7 +710,7 @@ impl Rc { } } - /// Returns a mutable reference into the given `Rc`, + /// Returns a mutable reference to the inner value, /// without any check. /// /// See also [`get_mut`], which is safe and does appropriate checks. @@ -722,7 +719,7 @@ impl Rc { /// /// # Safety /// - /// Any other `Rc` or [`Weak`] pointers to the same allocation must not be dereferenced + /// 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`. @@ -748,8 +745,8 @@ impl Rc { #[inline] #[stable(feature = "ptr_eq", since = "1.17.0")] - /// Returns `true` if the two `Rc`s point to the same allocation - /// (in a vein similar to [`ptr::eq`]). + /// Returns `true` if the two `Rc`s point to the same value (not + /// just values that compare as equal). /// /// # Examples /// @@ -763,8 +760,6 @@ impl Rc { /// assert!(Rc::ptr_eq(&five, &same_five)); /// assert!(!Rc::ptr_eq(&five, &other_five)); /// ``` - /// - /// [`ptr::eq`]: ../../std/ptr/fn.eq.html pub fn ptr_eq(this: &Self, other: &Self) -> bool { this.ptr.as_ptr() == other.ptr.as_ptr() } @@ -773,12 +768,12 @@ impl Rc { impl Rc { /// Makes a mutable reference into the given `Rc`. /// - /// If there are other `Rc` pointers to the same allocation, then `make_mut` will - /// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also + /// If there are other `Rc` pointers to the same value, then `make_mut` will + /// [`clone`] the inner value to ensure unique ownership. This is also /// referred to as clone-on-write. /// - /// If there are no other `Rc` pointers to this allocation, then [`Weak`] - /// pointers to this allocation will be disassociated. + /// If there are no other `Rc` pointers to this value, then [`Weak`] + /// pointers to this value will be dissassociated. /// /// See also [`get_mut`], which will fail rather than cloning. /// @@ -799,12 +794,12 @@ impl Rc { /// *Rc::make_mut(&mut data) += 1; // Won't clone anything /// *Rc::make_mut(&mut other_data) *= 2; // Won't clone anything /// - /// // Now `data` and `other_data` point to different allocations. + /// // Now `data` and `other_data` point to different values. /// assert_eq!(*data, 8); /// assert_eq!(*other_data, 12); /// ``` /// - /// [`Weak`] pointers will be disassociated: + /// [`Weak`] pointers will be dissassociated: /// /// ``` /// use std::rc::Rc; @@ -842,7 +837,7 @@ impl Rc { // returned is the *only* pointer that will ever be returned to T. Our // reference count is guaranteed to be 1 at this point, and we required // the `Rc` itself to be `mut`, so we're returning the only possible - // reference to the allocation. + // reference to the inner value. unsafe { &mut this.ptr.as_mut().value } @@ -866,9 +861,11 @@ impl Rc { /// } /// } /// - /// let my_string = "Hello World".to_string(); - /// print_if_string(Rc::new(my_string)); - /// print_if_string(Rc::new(0i8)); + /// fn main() { + /// let my_string = "Hello World".to_string(); + /// print_if_string(Rc::new(my_string)); + /// print_if_string(Rc::new(0i8)); + /// } /// ``` pub fn downcast(self) -> Result, Rc> { if (*self).is::() { @@ -883,7 +880,7 @@ impl Rc { impl Rc { /// Allocates an `RcBox` with sufficient space for - /// a possibly-unsized inner 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`. @@ -913,7 +910,7 @@ impl Rc { inner } - /// Allocates an `RcBox` with sufficient space for an unsized inner value + /// 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_layout( @@ -1116,7 +1113,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc { impl Clone for Rc { /// Makes a clone of the `Rc` pointer. /// - /// This creates another pointer to the same allocation, increasing the + /// This creates another pointer to the same inner value, increasing the /// strong reference count. /// /// # Examples @@ -1177,8 +1174,6 @@ impl RcEqIdent for Rc { /// store large values, that are slow to clone, but also heavy to check for equality, causing this /// cost to pay off more easily. It's also more likely to have two `Rc` clones, that point to /// the same value, than two `&T`s. -/// -/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive. #[stable(feature = "rust1", since = "1.0.0")] impl RcEqIdent for Rc { #[inline] @@ -1196,11 +1191,9 @@ impl RcEqIdent for Rc { impl PartialEq for Rc { /// Equality for two `Rc`s. /// - /// Two `Rc`s are equal if their inner values are equal, even if they are - /// stored in different allocation. + /// Two `Rc`s are equal if their inner values are equal. /// - /// If `T` also implements `Eq` (implying reflexivity of equality), - /// two `Rc`s that point to the same allocation are + /// If `T` also implements `Eq`, two `Rc`s that point to the same value are /// always equal. /// /// # Examples @@ -1221,8 +1214,7 @@ impl PartialEq for Rc { /// /// Two `Rc`s are unequal if their inner values are unequal. /// - /// If `T` also implements `Eq` (implying reflexivity of equality), - /// two `Rc`s that point to the same allocation are + /// If `T` also implements `Eq`, two `Rc`s that point to the same value are /// never unequal. /// /// # Examples @@ -1551,18 +1543,17 @@ impl<'a, T: 'a + Clone> RcFromIter<&'a T, slice::Iter<'a, T>> for Rc<[T]> { } /// `Weak` is a version of [`Rc`] that holds a non-owning reference to the -/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak` +/// managed value. The value is accessed by calling [`upgrade`] on the `Weak` /// pointer, which returns an [`Option`]`<`[`Rc`]`>`. /// /// Since a `Weak` reference does not count towards ownership, it will not -/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no -/// guarantees about the value still being present. Thus it may return [`None`] -/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation -/// itself (the backing store) from being deallocated. +/// prevent the inner value from being dropped, and `Weak` itself makes no +/// guarantees about the value still being present and may return [`None`] +/// when [`upgrade`]d. /// -/// A `Weak` pointer is useful for keeping a temporary reference to the allocation -/// managed by [`Rc`] without preventing its inner value from being dropped. It is also used to -/// prevent circular references between [`Rc`] pointers, since mutual owning references +/// A `Weak` pointer is useful for keeping a temporary reference to the value +/// within [`Rc`] without extending its lifetime. It is also used to prevent +/// circular references between [`Rc`] pointers, since mutual owning references /// would never allow either [`Rc`] to be dropped. For example, a tree could /// have strong [`Rc`] pointers from parent nodes to children, and `Weak` /// pointers from children back to their parents. @@ -1761,10 +1752,10 @@ pub(crate) fn is_dangling(ptr: NonNull) -> bool { } impl Weak { - /// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying - /// dropping of the inner value if successful. + /// Attempts to upgrade the `Weak` pointer to an [`Rc`], extending + /// the lifetime of the value if successful. /// - /// Returns [`None`] if the inner value has since been dropped. + /// Returns [`None`] if the value has since been dropped. /// /// [`Rc`]: struct.Rc.html /// [`None`]: ../../std/option/enum.Option.html @@ -1798,7 +1789,7 @@ impl Weak { } } - /// Gets the number of strong (`Rc`) pointers pointing to this allocation. + /// Gets the number of strong (`Rc`) pointers pointing to this value. /// /// If `self` was created using [`Weak::new`], this will return 0. /// @@ -1812,11 +1803,11 @@ impl Weak { } } - /// Gets the number of `Weak` pointers pointing to this allocation. + /// Gets the number of `Weak` pointers pointing to this value. /// /// If `self` was created using [`Weak::new`], this will return `None`. If /// not, the returned value is at least 1, since `self` still points to the - /// allocation. + /// value. /// /// [`Weak::new`]: #method.new #[unstable(feature = "weak_counts", issue = "57977")] @@ -1841,14 +1832,14 @@ impl Weak { } } - /// Returns `true` if the two `Weak`s point to the same allocation (similar to - /// [`ptr::eq`]), or if both don't point to any allocation + /// 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 allocation. + /// other, even though they don't point to any value. /// /// # Examples /// @@ -1880,8 +1871,6 @@ impl Weak { /// let third = Rc::downgrade(&third_rc); /// assert!(!first.ptr_eq(&third)); /// ``` - /// - /// [`ptr::eq`]: ../../std/ptr/fn.eq.html #[inline] #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { @@ -1931,7 +1920,7 @@ impl Drop for Weak { #[stable(feature = "rc_weak", since = "1.4.0")] impl Clone for Weak { - /// Makes a clone of the `Weak` pointer that points to the same allocation. + /// Makes a clone of the `Weak` pointer that points to the same value. /// /// # Examples /// diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 08243ef7c519f..881d499c0745b 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -411,16 +411,25 @@ impl [T] { /// Basic usage: /// /// ``` - /// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]); + /// #![feature(repeat_generic_slice)] + /// + /// fn main() { + /// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]); + /// } /// ``` /// /// A panic upon overflow: /// /// ```should_panic - /// // this will panic at runtime - /// b"0123456789abcdef".repeat(usize::max_value()); + /// #![feature(repeat_generic_slice)] + /// fn main() { + /// // this will panic at runtime + /// b"0123456789abcdef".repeat(usize::max_value()); + /// } /// ``` - #[stable(feature = "repeat_generic_slice", since = "1.40.0")] + #[unstable(feature = "repeat_generic_slice", + reason = "it's on str, why not on slice?", + issue = "48784")] pub fn repeat(&self, n: usize) -> Vec where T: Copy { if n == 0 { return Vec::new(); diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 83816d8b954c4..9a1342c30d502 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -456,7 +456,7 @@ impl str { } } } - s + return s; } /// Converts a [`Box`] into a [`String`] without copying or allocating. @@ -500,8 +500,10 @@ impl str { /// A panic upon overflow: /// /// ```should_panic - /// // this will panic at runtime - /// "0123456789abcdef".repeat(usize::max_value()); + /// fn main() { + /// // this will panic at runtime + /// "0123456789abcdef".repeat(usize::max_value()); + /// } /// ``` #[stable(feature = "repeat_str", since = "1.16.0")] pub fn repeat(&self, n: usize) -> String { diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 639124e26cc20..abe50fdb7a396 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -164,8 +164,10 @@ use crate::vec::Vec; /// /// fn example_func(example_arg: A) {} /// -/// let example_string = String::from("example_string"); -/// example_func(&example_string); +/// fn main() { +/// let example_string = String::from("example_string"); +/// example_func(&example_string); +/// } /// ``` /// /// There are two options that would work instead. The first would be to diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 80d6c6e0d4390..45f98162e4cd5 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -45,10 +45,10 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// /// The type `Arc` provides shared ownership of a value of type `T`, /// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces -/// a new `Arc` instance, which points to the same allocation on the heap as the +/// a new `Arc` instance, which points to the same value on the heap as the /// source `Arc`, while increasing a reference count. When the last `Arc` -/// pointer to a given allocation is destroyed, the value stored in that allocation (often -/// referred to as "inner value") is also dropped. +/// pointer to a given value is destroyed, the pointed-to value is also +/// destroyed. /// /// Shared references in Rust disallow mutation by default, and `Arc` is no /// exception: you cannot generally obtain a mutable reference to something @@ -61,7 +61,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// Unlike [`Rc`], `Arc` uses atomic operations for its reference /// counting. This means that it is thread-safe. The disadvantage is that /// atomic operations are more expensive than ordinary memory accesses. If you -/// are not sharing reference-counted allocations between threads, consider using +/// are not sharing reference-counted values between threads, consider using /// [`Rc`] for lower overhead. [`Rc`] is a safe default, because the /// compiler will catch any attempt to send an [`Rc`] between threads. /// However, a library might choose `Arc` in order to give library consumers @@ -85,10 +85,8 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// /// The [`downgrade`][downgrade] method can be used to create a non-owning /// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d -/// to an `Arc`, but this will return [`None`] if the value stored in the allocation has -/// already been dropped. In other words, `Weak` pointers do not keep the value -/// inside the allocation alive; however, they *do* keep the allocation -/// (the backing store for the value) alive. +/// to an `Arc`, but this will return [`None`] if the value has already been +/// dropped. /// /// A cycle between `Arc` pointers will never be deallocated. For this reason, /// [`Weak`][weak] is used to break cycles. For example, a tree could have @@ -123,8 +121,8 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// Arc::downgrade(&my_arc); /// ``` /// -/// [`Weak`][weak] does not auto-dereference to `T`, because the inner value may have -/// already been dropped. +/// [`Weak`][weak] does not auto-dereference to `T`, because the value may have +/// already been destroyed. /// /// [arc]: struct.Arc.html /// [weak]: struct.Weak.html @@ -223,18 +221,17 @@ impl Arc { } /// `Weak` is a version of [`Arc`] that holds a non-owning reference to the -/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak` +/// managed value. The value is accessed by calling [`upgrade`] on the `Weak` /// pointer, which returns an [`Option`]`<`[`Arc`]`>`. /// /// Since a `Weak` reference does not count towards ownership, it will not -/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no -/// guarantees about the value still being present. Thus it may return [`None`] -/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation -/// itself (the backing store) from being deallocated. +/// prevent the inner value from being dropped, and `Weak` itself makes no +/// guarantees about the value still being present and may return [`None`] +/// when [`upgrade`]d. /// -/// A `Weak` pointer is useful for keeping a temporary reference to the allocation -/// managed by [`Arc`] without preventing its inner value from being dropped. It is also used to -/// prevent circular references between [`Arc`] pointers, since mutual owning references +/// A `Weak` pointer is useful for keeping a temporary reference to the value +/// within [`Arc`] without extending its lifetime. It is also used to prevent +/// circular references between [`Arc`] pointers, since mutual owning references /// would never allow either [`Arc`] to be dropped. For example, a tree could /// have strong [`Arc`] pointers from parent nodes to children, and `Weak` /// pointers from children back to their parents. @@ -348,7 +345,7 @@ impl Arc { unsafe { Pin::new_unchecked(Arc::new(data)) } } - /// Returns the inner value, if the `Arc` has exactly one strong reference. + /// Returns the contained value, if the `Arc` has exactly one strong reference. /// /// Otherwise, an [`Err`][result] is returned with the same `Arc` that was /// passed in. @@ -429,7 +426,7 @@ impl Arc> { /// # Safety /// /// As with [`MaybeUninit::assume_init`], - /// it is up to the caller to guarantee that the inner value + /// 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. @@ -468,7 +465,7 @@ impl Arc<[mem::MaybeUninit]> { /// # Safety /// /// As with [`MaybeUninit::assume_init`], - /// it is up to the caller to guarantee that the inner value + /// 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. @@ -587,7 +584,7 @@ impl Arc { unsafe { NonNull::new_unchecked(Arc::into_raw(this) as *mut _) } } - /// Creates a new [`Weak`][weak] pointer to this allocation. + /// Creates a new [`Weak`][weak] pointer to this value. /// /// [weak]: struct.Weak.html /// @@ -631,7 +628,7 @@ impl Arc { } } - /// Gets the number of [`Weak`][weak] pointers to this allocation. + /// Gets the number of [`Weak`][weak] pointers to this value. /// /// [weak]: struct.Weak.html /// @@ -662,7 +659,7 @@ impl Arc { if cnt == usize::MAX { 0 } else { cnt - 1 } } - /// Gets the number of strong (`Arc`) pointers to this allocation. + /// Gets the number of strong (`Arc`) pointers to this value. /// /// # Safety /// @@ -713,8 +710,8 @@ impl Arc { #[inline] #[stable(feature = "ptr_eq", since = "1.17.0")] - /// Returns `true` if the two `Arc`s point to the same allocation - /// (in a vein similar to [`ptr::eq`]). + /// Returns `true` if the two `Arc`s point to the same value (not + /// just values that compare as equal). /// /// # Examples /// @@ -728,8 +725,6 @@ impl Arc { /// assert!(Arc::ptr_eq(&five, &same_five)); /// assert!(!Arc::ptr_eq(&five, &other_five)); /// ``` - /// - /// [`ptr::eq`]: ../../std/ptr/fn.eq.html pub fn ptr_eq(this: &Self, other: &Self) -> bool { this.ptr.as_ptr() == other.ptr.as_ptr() } @@ -737,7 +732,7 @@ impl Arc { impl Arc { /// Allocates an `ArcInner` with sufficient space for - /// a possibly-unsized inner 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`. @@ -766,7 +761,7 @@ impl Arc { inner } - /// Allocates an `ArcInner` with sufficient space for an unsized inner value. + /// 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_layout( @@ -908,7 +903,7 @@ impl ArcFromSlice for Arc<[T]> { impl Clone for Arc { /// Makes a clone of the `Arc` pointer. /// - /// This creates another pointer to the same allocation, increasing the + /// This creates another pointer to the same inner value, increasing the /// strong reference count. /// /// # Examples @@ -970,19 +965,15 @@ impl Receiver for Arc {} impl Arc { /// Makes a mutable reference into the given `Arc`. /// - /// If there are other `Arc` or [`Weak`][weak] pointers to the same allocation, - /// then `make_mut` will create a new allocation and invoke [`clone`][clone] on the inner value - /// to ensure unique ownership. This is also referred to as clone-on-write. - /// - /// Note that this differs from the behavior of [`Rc::make_mut`] which disassociates - /// any remaining `Weak` pointers. + /// If there are other `Arc` or [`Weak`][weak] pointers to the same value, + /// then `make_mut` will invoke [`clone`][clone] on the inner value to + /// ensure unique ownership. This is also referred to as clone-on-write. /// /// See also [`get_mut`][get_mut], which will fail rather than cloning. /// /// [weak]: struct.Weak.html /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone /// [get_mut]: struct.Arc.html#method.get_mut - /// [`Rc::make_mut`]: ../rc/struct.Rc.html#method.make_mut /// /// # Examples /// @@ -997,7 +988,7 @@ impl Arc { /// *Arc::make_mut(&mut data) += 1; // Won't clone anything /// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything /// - /// // Now `data` and `other_data` point to different allocations. + /// // Now `data` and `other_data` point to different values. /// assert_eq!(*data, 8); /// assert_eq!(*other_data, 12); /// ``` @@ -1057,14 +1048,14 @@ impl Arc { } impl Arc { - /// Returns a mutable reference into the given `Arc`, if there are - /// no other `Arc` or [`Weak`][weak] pointers to the same allocation. + /// Returns a mutable reference to the inner value, if there are + /// no other `Arc` or [`Weak`][weak] pointers to the same value. /// /// Returns [`None`][option] otherwise, because it is not safe to /// mutate a shared value. /// /// See also [`make_mut`][make_mut], which will [`clone`][clone] - /// the inner value when there are other pointers. + /// the inner value when it's shared. /// /// [weak]: struct.Weak.html /// [option]: ../../std/option/enum.Option.html @@ -1100,7 +1091,7 @@ impl Arc { } } - /// Returns a mutable reference into the given `Arc`, + /// Returns a mutable reference to the inner value, /// without any check. /// /// See also [`get_mut`], which is safe and does appropriate checks. @@ -1109,7 +1100,7 @@ impl Arc { /// /// # Safety /// - /// Any other `Arc` or [`Weak`] pointers to the same allocation must not be dereferenced + /// 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`. @@ -1253,9 +1244,11 @@ impl Arc { /// } /// } /// - /// let my_string = "Hello World".to_string(); - /// print_if_string(Arc::new(my_string)); - /// print_if_string(Arc::new(0i8)); + /// fn main() { + /// let my_string = "Hello World".to_string(); + /// print_if_string(Arc::new(my_string)); + /// print_if_string(Arc::new(0i8)); + /// } /// ``` pub fn downcast(self) -> Result, Self> where @@ -1433,10 +1426,10 @@ impl Weak { } impl Weak { - /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying - /// dropping of the inner value if successful. + /// Attempts to upgrade the `Weak` pointer to an [`Arc`], extending + /// the lifetime of the value if successful. /// - /// Returns [`None`] if the inner value has since been dropped. + /// Returns [`None`] if the value has since been dropped. /// /// [`Arc`]: struct.Arc.html /// [`None`]: ../../std/option/enum.Option.html#variant.None @@ -1491,7 +1484,7 @@ impl Weak { } } - /// Gets the number of strong (`Arc`) pointers pointing to this allocation. + /// Gets the number of strong (`Arc`) pointers pointing to this value. /// /// If `self` was created using [`Weak::new`], this will return 0. /// @@ -1506,17 +1499,17 @@ impl Weak { } /// Gets an approximation of the number of `Weak` pointers pointing to this - /// allocation. + /// value. /// /// If `self` was created using [`Weak::new`], this will return 0. If not, /// the returned value is at least 1, since `self` still points to the - /// allocation. + /// value. /// /// # Accuracy /// /// Due to implementation details, the returned value can be off by 1 in /// either direction when other threads are manipulating any `Arc`s or - /// `Weak`s pointing to the same allocation. + /// `Weak`s pointing to the same value. /// /// [`Weak::new`]: #method.new #[unstable(feature = "weak_counts", issue = "57977")] @@ -1557,14 +1550,14 @@ impl Weak { } } - /// Returns `true` if the two `Weak`s point to the same allocation (similar to - /// [`ptr::eq`]), or if both don't point to any allocation + /// 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 allocation. + /// other, even though they don't point to any value. /// /// # Examples /// @@ -1596,8 +1589,6 @@ impl Weak { /// let third = Arc::downgrade(&third_rc); /// assert!(!first.ptr_eq(&third)); /// ``` - /// - /// [`ptr::eq`]: ../../std/ptr/fn.eq.html #[inline] #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { @@ -1607,7 +1598,7 @@ impl Weak { #[stable(feature = "arc_weak", since = "1.4.0")] impl Clone for Weak { - /// Makes a clone of the `Weak` pointer that points to the same allocation. + /// Makes a clone of the `Weak` pointer that points to the same value. /// /// # Examples /// @@ -1638,7 +1629,7 @@ impl Clone for Weak { } } - Weak { ptr: self.ptr } + return Weak { ptr: self.ptr }; } } @@ -1737,8 +1728,6 @@ impl ArcEqIdent for Arc { /// store large values, that are slow to clone, but also heavy to check for equality, causing this /// cost to pay off more easily. It's also more likely to have two `Arc` clones, that point to /// the same value, than two `&T`s. -/// -/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive. #[stable(feature = "rust1", since = "1.0.0")] impl ArcEqIdent for Arc { #[inline] @@ -1756,11 +1745,10 @@ impl ArcEqIdent for Arc { impl PartialEq for Arc { /// Equality for two `Arc`s. /// - /// Two `Arc`s are equal if their inner values are equal, even if they are - /// stored in different allocation. + /// Two `Arc`s are equal if their inner values are equal. /// - /// If `T` also implements `Eq` (implying reflexivity of equality), - /// two `Arc`s that point to the same allocation are always equal. + /// If `T` also implements `Eq`, two `Arc`s that point to the same value are + /// always equal. /// /// # Examples /// @@ -1780,8 +1768,8 @@ impl PartialEq for Arc { /// /// Two `Arc`s are unequal if their inner values are unequal. /// - /// If `T` also implements `Eq` (implying reflexivity of equality), - /// two `Arc`s that point to the same value are never unequal. + /// If `T` also implements `Eq`, two `Arc`s that point to the same value are + /// never unequal. /// /// # Examples /// diff --git a/src/liballoc/tests/binary_heap.rs b/src/liballoc/tests/binary_heap.rs index b8c720264d0ab..0685fa943c0b8 100644 --- a/src/liballoc/tests/binary_heap.rs +++ b/src/liballoc/tests/binary_heap.rs @@ -1,5 +1,10 @@ +use std::cmp; use std::collections::BinaryHeap; use std::collections::binary_heap::{Drain, PeekMut}; +use std::panic::{self, AssertUnwindSafe}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +use rand::{thread_rng, seq::SliceRandom}; #[test] fn test_iterator() { @@ -276,15 +281,9 @@ fn assert_covariance() { // even if the order may not be correct. // // Destructors must be called exactly once per element. -// FIXME: re-enable emscripten once it can unwind again #[test] -#[cfg(not(any(miri, target_os = "emscripten")))] // Miri does not support catching panics +#[cfg(not(miri))] // Miri does not support catching panics fn panic_safe() { - use std::cmp; - use std::panic::{self, AssertUnwindSafe}; - use std::sync::atomic::{AtomicUsize, Ordering}; - use rand::{thread_rng, seq::SliceRandom}; - static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); #[derive(Eq, PartialEq, Ord, Clone, Debug)] diff --git a/src/liballoc/tests/boxed.rs b/src/liballoc/tests/boxed.rs deleted file mode 100644 index bc3d53bf30da3..0000000000000 --- a/src/liballoc/tests/boxed.rs +++ /dev/null @@ -1,18 +0,0 @@ -use std::ptr::NonNull; -use std::mem::MaybeUninit; - -#[test] -fn unitialized_zero_size_box() { - assert_eq!( - &*Box::<()>::new_uninit() as *const _, - NonNull::>::dangling().as_ptr(), - ); - assert_eq!( - Box::<[()]>::new_uninit_slice(4).as_ptr(), - NonNull::>::dangling().as_ptr(), - ); - assert_eq!( - Box::<[String]>::new_uninit_slice(0).as_ptr(), - NonNull::>::dangling().as_ptr(), - ); -} diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index e4883abc8b56c..35db18c39c83a 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -48,9 +48,7 @@ fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) f(&set_a, &set_b, &mut |&x| { - if i < expected.len() { - assert_eq!(x, expected[i]); - } + assert_eq!(x, expected[i]); i += 1; true }); @@ -76,20 +74,20 @@ fn test_intersection() { return; } - let large = (0..100).collect::>(); + let large = (0..1000).collect::>(); check_intersection(&[], &large, &[]); check_intersection(&large, &[], &[]); check_intersection(&[-1], &large, &[]); check_intersection(&large, &[-1], &[]); check_intersection(&[0], &large, &[0]); check_intersection(&large, &[0], &[0]); - check_intersection(&[99], &large, &[99]); - check_intersection(&large, &[99], &[99]); - check_intersection(&[100], &large, &[]); - check_intersection(&large, &[100], &[]); - check_intersection(&[11, 5000, 1, 3, 77, 8924], + check_intersection(&[999], &large, &[999]); + check_intersection(&large, &[999], &[999]); + check_intersection(&[1000], &large, &[]); + check_intersection(&large, &[1000], &[]); + check_intersection(&[11, 5000, 1, 3, 77, 8924, 103], &large, - &[1, 3, 11, 77]); + &[1, 3, 11, 77, 103]); } #[test] @@ -97,15 +95,10 @@ 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(), (1, Some(1))); + 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); - - iter = y.intersection(&y); - assert_eq!(iter.size_hint(), (0, Some(3))); - assert_eq!(iter.next(), Some(&1)); - assert_eq!(iter.size_hint(), (0, Some(2))); } #[test] @@ -118,9 +111,6 @@ fn test_difference() { check_difference(&[1, 12], &[], &[1, 12]); check_difference(&[], &[1, 2, 3, 9], &[]); check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]); - check_difference(&[1, 3, 5, 9, 11], &[3, 6, 9], &[1, 5, 11]); - check_difference(&[1, 3, 5, 9, 11], &[0, 1], &[3, 5, 9, 11]); - check_difference(&[1, 3, 5, 9, 11], &[11, 12], &[1, 3, 5, 9]); check_difference(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 14, 23, 34, 38, 39, 50], &[11, 22, 33, 40, 42]); @@ -129,82 +119,18 @@ fn test_difference() { return; } - let large = (0..100).collect::>(); + let large = (0..1000).collect::>(); check_difference(&[], &large, &[]); check_difference(&[-1], &large, &[-1]); check_difference(&[0], &large, &[]); - check_difference(&[99], &large, &[]); - check_difference(&[100], &large, &[100]); - check_difference(&[11, 5000, 1, 3, 77, 8924], + check_difference(&[999], &large, &[]); + check_difference(&[1000], &large, &[1000]); + check_difference(&[11, 5000, 1, 3, 77, 8924, 103], &large, &[5000, 8924]); check_difference(&large, &[], &large); check_difference(&large, &[-1], &large); - check_difference(&large, &[100], &large); -} - -#[test] -fn test_difference_size_hint() { - let s246: BTreeSet = [2, 4, 6].iter().copied().collect(); - let s23456: BTreeSet = (2..=6).collect(); - let mut iter = s246.difference(&s23456); - assert_eq!(iter.size_hint(), (0, Some(3))); - assert_eq!(iter.next(), None); - - let s12345: BTreeSet = (1..=5).collect(); - iter = s246.difference(&s12345); - assert_eq!(iter.size_hint(), (0, Some(3))); - assert_eq!(iter.next(), Some(&6)); - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - - let s34567: BTreeSet = (3..=7).collect(); - iter = s246.difference(&s34567); - assert_eq!(iter.size_hint(), (0, Some(3))); - assert_eq!(iter.next(), Some(&2)); - assert_eq!(iter.size_hint(), (0, Some(2))); - assert_eq!(iter.next(), None); - - let s1: BTreeSet = (-9..=1).collect(); - iter = s246.difference(&s1); - assert_eq!(iter.size_hint(), (3, Some(3))); - - let s2: BTreeSet = (-9..=2).collect(); - iter = s246.difference(&s2); - assert_eq!(iter.size_hint(), (2, Some(2))); - assert_eq!(iter.next(), Some(&4)); - assert_eq!(iter.size_hint(), (1, Some(1))); - - let s23: BTreeSet = (2..=3).collect(); - iter = s246.difference(&s23); - assert_eq!(iter.size_hint(), (1, Some(3))); - assert_eq!(iter.next(), Some(&4)); - assert_eq!(iter.size_hint(), (1, Some(1))); - - let s4: BTreeSet = (4..=4).collect(); - iter = s246.difference(&s4); - assert_eq!(iter.size_hint(), (2, Some(3))); - assert_eq!(iter.next(), Some(&2)); - assert_eq!(iter.size_hint(), (1, Some(2))); - assert_eq!(iter.next(), Some(&6)); - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - - let s56: BTreeSet = (5..=6).collect(); - iter = s246.difference(&s56); - assert_eq!(iter.size_hint(), (1, Some(3))); - assert_eq!(iter.next(), Some(&2)); - assert_eq!(iter.size_hint(), (0, Some(2))); - - let s6: BTreeSet = (6..=19).collect(); - iter = s246.difference(&s6); - assert_eq!(iter.size_hint(), (2, Some(2))); - assert_eq!(iter.next(), Some(&2)); - assert_eq!(iter.size_hint(), (1, Some(1))); - - let s7: BTreeSet = (7..=19).collect(); - iter = s246.difference(&s7); - assert_eq!(iter.size_hint(), (3, Some(3))); + check_difference(&large, &[1000], &large); } #[test] @@ -221,18 +147,6 @@ fn test_symmetric_difference() { &[-2, 1, 5, 11, 14, 22]); } -#[test] -fn test_symmetric_difference_size_hint() { - let x: BTreeSet = [2, 4].iter().copied().collect(); - let y: BTreeSet = [1, 2, 3].iter().copied().collect(); - let mut iter = x.symmetric_difference(&y); - assert_eq!(iter.size_hint(), (0, Some(5))); - assert_eq!(iter.next(), Some(&1)); - assert_eq!(iter.size_hint(), (0, Some(4))); - assert_eq!(iter.next(), Some(&3)); - assert_eq!(iter.size_hint(), (0, Some(1))); -} - #[test] fn test_union() { fn check_union(a: &[i32], b: &[i32], expected: &[i32]) { @@ -247,18 +161,6 @@ fn test_union() { &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); } -#[test] -fn test_union_size_hint() { - let x: BTreeSet = [2, 4].iter().copied().collect(); - let y: BTreeSet = [1, 2, 3].iter().copied().collect(); - let mut iter = x.union(&y); - assert_eq!(iter.size_hint(), (3, Some(5))); - assert_eq!(iter.next(), Some(&1)); - assert_eq!(iter.size_hint(), (2, Some(4))); - assert_eq!(iter.next(), Some(&2)); - assert_eq!(iter.size_hint(), (1, Some(2))); -} - #[test] // Only tests the simple function definition with respect to intersection fn test_is_disjoint() { @@ -268,7 +170,7 @@ fn test_is_disjoint() { } #[test] -// Also implicitly tests the trivial function definition of is_superset +// Also tests the trivial function definition of is_superset fn test_is_subset() { fn is_subset(a: &[i32], b: &[i32]) -> bool { let set_a = a.iter().collect::>(); @@ -286,23 +188,23 @@ fn test_is_subset() { assert_eq!(is_subset(&[1, 2], &[1, 2]), true); assert_eq!(is_subset(&[1, 2], &[2, 3]), false); assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], - &[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42]), + &[-12, -5, 14, 23, 11, 34, 22, 38, 33, 42, 39, 40]), true); assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], - &[-12, -5, 11, 14, 22, 23, 34, 38]), + &[-12, -5, 14, 23, 34, 38, 22, 11]), false); if cfg!(miri) { // Miri is too slow return; } - let large = (0..100).collect::>(); + let large = (0..1000).collect::>(); assert_eq!(is_subset(&[], &large), true); assert_eq!(is_subset(&large, &[]), false); assert_eq!(is_subset(&[-1], &large), false); assert_eq!(is_subset(&[0], &large), true); assert_eq!(is_subset(&[1, 2], &large), true); - assert_eq!(is_subset(&[99, 100], &large), false); + assert_eq!(is_subset(&[999, 1000], &large), false); } #[test] diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 676874c8b27df..5723a30c0f34f 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -2,9 +2,9 @@ #![feature(box_syntax)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] -#![feature(new_uninit)] #![feature(option_flattening)] #![feature(pattern)] +#![feature(repeat_generic_slice)] #![feature(trusted_len)] #![feature(try_reserve)] #![feature(unboxed_closures)] @@ -15,7 +15,6 @@ use std::collections::hash_map::DefaultHasher; mod arc; mod binary_heap; -mod boxed; mod btree; mod cow_str; mod fmt; diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index cb73c7c179cbf..4332b2e90fdaf 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -483,7 +483,7 @@ mod slice_index { } #[test] - #[cfg(not(target_os = "emscripten"))] // hits an OOM + #[cfg(not(target_arch = "asmjs"))] // hits an OOM #[cfg(not(miri))] // Miri is too slow fn simple_big() { fn a_million_letter_x() -> String { diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 80537217697ad..29a22aa0315b0 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -944,10 +944,8 @@ fn drain_filter_complex() { } } -// Miri does not support catching panics -// FIXME: re-enable emscripten once it can unwind again #[test] -#[cfg(not(any(miri, target_os = "emscripten")))] +#[cfg(not(miri))] // Miri does not support catching panics fn drain_filter_consumed_panic() { use std::rc::Rc; use std::sync::Mutex; @@ -997,9 +995,8 @@ fn drain_filter_consumed_panic() { } } -// FIXME: Re-enable emscripten once it can catch panics #[test] -#[cfg(not(any(miri, target_os = "emscripten")))] // Miri does not support catching panics +#[cfg(not(miri))] // Miri does not support catching panics fn drain_filter_unconsumed_panic() { use std::rc::Rc; use std::sync::Mutex; @@ -1284,51 +1281,3 @@ fn test_stable_push_pop() { v.pop().unwrap(); assert_eq!(*v0, 13); } - -// https://github.com/rust-lang/rust/pull/49496 introduced specialization based on: -// -// ``` -// unsafe impl IsZero for *mut T { -// fn is_zero(&self) -> bool { -// (*self).is_null() -// } -// } -// ``` -// -// … to call `RawVec::with_capacity_zeroed` for creating `Vec<*mut T>`, -// which is incorrect for fat pointers since `<*mut T>::is_null` only looks at the data component. -// That is, a fat pointer can be “null” without being made entirely of zero bits. -#[test] -fn vec_macro_repeating_null_raw_fat_pointer() { - let raw_dyn = &mut (|| ()) as &mut dyn Fn() as *mut dyn Fn(); - let vtable = dbg!(ptr_metadata(raw_dyn)); - let null_raw_dyn = ptr_from_raw_parts(std::ptr::null_mut(), vtable); - assert!(null_raw_dyn.is_null()); - - let vec = vec![null_raw_dyn; 1]; - dbg!(ptr_metadata(vec[0])); - assert!(vec[0] == null_raw_dyn); - - // Polyfill for https://github.com/rust-lang/rfcs/pull/2580 - - fn ptr_metadata(ptr: *mut dyn Fn()) -> *mut () { - unsafe { - std::mem::transmute::<*mut dyn Fn(), DynRepr>(ptr).vtable - } - } - - fn ptr_from_raw_parts(data: *mut (), vtable: *mut()) -> *mut dyn Fn() { - unsafe { - std::mem::transmute::(DynRepr { - data, - vtable - }) - } - } - - #[repr(C)] - struct DynRepr { - data: *mut (), - vtable: *mut (), - } -} diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 6350b189c5faa..e5672f8542ff6 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -389,26 +389,28 @@ impl Vec { /// use std::ptr; /// use std::mem; /// - /// let mut v = vec![1, 2, 3]; + /// fn main() { + /// let mut v = vec![1, 2, 3]; /// - /// // Pull out the various important pieces of information about `v` - /// let p = v.as_mut_ptr(); - /// let len = v.len(); - /// let cap = v.capacity(); + /// // Pull out the various important pieces of information about `v` + /// let p = v.as_mut_ptr(); + /// let len = v.len(); + /// let cap = v.capacity(); /// - /// unsafe { - /// // Cast `v` into the void: no destructor run, so we are in - /// // complete control of the allocation to which `p` points. - /// mem::forget(v); + /// unsafe { + /// // Cast `v` into the void: no destructor run, so we are in + /// // complete control of the allocation to which `p` points. + /// mem::forget(v); /// - /// // Overwrite memory with 4, 5, 6 - /// for i in 0..len as isize { - /// ptr::write(p.offset(i), 4 + i); - /// } + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len as isize { + /// ptr::write(p.offset(i), 4 + i); + /// } /// - /// // Put everything back together into a Vec - /// let rebuilt = Vec::from_raw_parts(p, len, cap); - /// assert_eq!(rebuilt, [4, 5, 6]); + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_raw_parts(p, len, cap); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1389,10 +1391,12 @@ impl Vec { /// ``` /// #![feature(vec_leak)] /// - /// let x = vec![1, 2, 3]; - /// let static_ref: &'static mut [usize] = Vec::leak(x); - /// static_ref[0] += 1; - /// assert_eq!(static_ref, &[2, 2, 3]); + /// fn main() { + /// let x = vec![1, 2, 3]; + /// let static_ref: &'static mut [usize] = Vec::leak(x); + /// static_ref[0] += 1; + /// assert_eq!(static_ref, &[2, 2, 3]); + /// } /// ``` #[unstable(feature = "vec_leak", issue = "62195")] #[inline] @@ -1730,45 +1734,20 @@ impl_is_zero!(char, |x| x == '\0'); impl_is_zero!(f32, |x: f32| x.to_bits() == 0); impl_is_zero!(f64, |x: f64| x.to_bits() == 0); -unsafe impl IsZero for *const T { +unsafe impl IsZero for *const T { #[inline] fn is_zero(&self) -> bool { (*self).is_null() } } -unsafe impl IsZero for *mut T { +unsafe impl IsZero for *mut T { #[inline] fn is_zero(&self) -> bool { (*self).is_null() } } -// `Option<&T>`, `Option<&mut T>` and `Option>` are guaranteed to represent `None` as null. -// For fat pointers, the bytes that would be the pointer metadata in the `Some` variant -// are padding in the `None` variant, so ignoring them and zero-initializing instead is ok. - -unsafe impl IsZero for Option<&T> { - #[inline] - fn is_zero(&self) -> bool { - self.is_none() - } -} - -unsafe impl IsZero for Option<&mut T> { - #[inline] - fn is_zero(&self) -> bool { - self.is_none() - } -} - -unsafe impl IsZero for Option> { - #[inline] - fn is_zero(&self) -> bool { - self.is_none() - } -} - //////////////////////////////////////////////////////////////////////////////// // Common trait implementations for Vec diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 66d27a275192e..690d8344acff9 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -500,7 +500,7 @@ impl DroplessArena { // though it was supposed to give us `len` return slice::from_raw_parts_mut(mem, i); } - ptr::write(mem.add(i), value.unwrap()); + ptr::write(mem.offset(i as isize), value.unwrap()); i += 1; } } diff --git a/src/libcore/any.rs b/src/libcore/any.rs index e2704e807d104..0afbf4f134679 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -2,14 +2,14 @@ //! of any `'static` type through runtime reflection. //! //! `Any` itself can be used to get a `TypeId`, and has more features when used -//! as a trait object. As `&dyn Any` (a borrowed trait object), it has the `is` -//! and `downcast_ref` methods, to test if the contained value is of a given type, -//! and to get a reference to the inner value as a type. As `&mut dyn Any`, there +//! as a trait object. As `&Any` (a borrowed trait object), it has the `is` and +//! `downcast_ref` methods, to test if the contained value is of a given type, +//! and to get a reference to the inner value as a type. As `&mut Any`, there //! is also the `downcast_mut` method, for getting a mutable reference to the -//! inner value. `Box` adds the `downcast` method, which attempts to +//! inner value. `Box` adds the `downcast` method, which attempts to //! convert to a `Box`. See the [`Box`] documentation for the full details. //! -//! Note that `&dyn Any` is limited to testing whether a value is of a specified +//! Note that &Any is limited to testing whether a value is of a specified //! concrete type, and cannot be used to test whether a type implements a trait. //! //! [`Box`]: ../../std/boxed/struct.Box.html @@ -87,8 +87,10 @@ pub trait Any: 'static { /// TypeId::of::() == s.type_id() /// } /// - /// assert_eq!(is_string(&0), false); - /// assert_eq!(is_string(&"cookie monster".to_string()), true); + /// fn main() { + /// assert_eq!(is_string(&0), false); + /// assert_eq!(is_string(&"cookie monster".to_string()), true); + /// } /// ``` #[stable(feature = "get_type_id", since = "1.34.0")] fn type_id(&self) -> TypeId; @@ -143,8 +145,10 @@ impl dyn Any { /// } /// } /// - /// is_string(&0); - /// is_string(&"cookie monster".to_string()); + /// fn main() { + /// is_string(&0); + /// is_string(&"cookie monster".to_string()); + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -175,8 +179,10 @@ impl dyn Any { /// } /// } /// - /// print_if_string(&0); - /// print_if_string(&"cookie monster".to_string()); + /// fn main() { + /// print_if_string(&0); + /// print_if_string(&"cookie monster".to_string()); + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -204,14 +210,16 @@ impl dyn Any { /// } /// } /// - /// let mut x = 10u32; - /// let mut s = "starlord".to_string(); + /// fn main() { + /// let mut x = 10u32; + /// let mut s = "starlord".to_string(); /// - /// modify_if_u32(&mut x); - /// modify_if_u32(&mut s); + /// modify_if_u32(&mut x); + /// modify_if_u32(&mut s); /// - /// assert_eq!(x, 42); - /// assert_eq!(&s, "starlord"); + /// assert_eq!(x, 42); + /// assert_eq!(&s, "starlord"); + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -242,8 +250,10 @@ impl dyn Any+Send { /// } /// } /// - /// is_string(&0); - /// is_string(&"cookie monster".to_string()); + /// fn main() { + /// is_string(&0); + /// is_string(&"cookie monster".to_string()); + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -266,8 +276,10 @@ impl dyn Any+Send { /// } /// } /// - /// print_if_string(&0); - /// print_if_string(&"cookie monster".to_string()); + /// fn main() { + /// print_if_string(&0); + /// print_if_string(&"cookie monster".to_string()); + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -288,14 +300,16 @@ impl dyn Any+Send { /// } /// } /// - /// let mut x = 10u32; - /// let mut s = "starlord".to_string(); + /// fn main() { + /// let mut x = 10u32; + /// let mut s = "starlord".to_string(); /// - /// modify_if_u32(&mut x); - /// modify_if_u32(&mut s); + /// modify_if_u32(&mut x); + /// modify_if_u32(&mut s); /// - /// assert_eq!(x, 42); - /// assert_eq!(&s, "starlord"); + /// assert_eq!(x, 42); + /// assert_eq!(&s, "starlord"); + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -320,8 +334,10 @@ impl dyn Any+Send+Sync { /// } /// } /// - /// is_string(&0); - /// is_string(&"cookie monster".to_string()); + /// fn main() { + /// is_string(&0); + /// is_string(&"cookie monster".to_string()); + /// } /// ``` #[stable(feature = "any_send_sync_methods", since = "1.28.0")] #[inline] @@ -344,8 +360,10 @@ impl dyn Any+Send+Sync { /// } /// } /// - /// print_if_string(&0); - /// print_if_string(&"cookie monster".to_string()); + /// fn main() { + /// print_if_string(&0); + /// print_if_string(&"cookie monster".to_string()); + /// } /// ``` #[stable(feature = "any_send_sync_methods", since = "1.28.0")] #[inline] @@ -366,14 +384,16 @@ impl dyn Any+Send+Sync { /// } /// } /// - /// let mut x = 10u32; - /// let mut s = "starlord".to_string(); + /// fn main() { + /// let mut x = 10u32; + /// let mut s = "starlord".to_string(); /// - /// modify_if_u32(&mut x); - /// modify_if_u32(&mut s); + /// modify_if_u32(&mut x); + /// modify_if_u32(&mut s); /// - /// assert_eq!(x, 42); - /// assert_eq!(&s, "starlord"); + /// assert_eq!(x, 42); + /// assert_eq!(&s, "starlord"); + /// } /// ``` #[stable(feature = "any_send_sync_methods", since = "1.28.0")] #[inline] @@ -417,8 +437,10 @@ impl TypeId { /// TypeId::of::() == TypeId::of::() /// } /// - /// assert_eq!(is_string(&0), false); - /// assert_eq!(is_string(&"cookie monster".to_string()), true); + /// fn main() { + /// assert_eq!(is_string(&0), false); + /// assert_eq!(is_string(&"cookie monster".to_string()), true); + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature="const_type_id")] @@ -445,15 +467,6 @@ impl TypeId { /// /// The current implementation uses the same infrastructure as compiler /// diagnostics and debuginfo, but this is not guaranteed. -/// -/// # Example -/// -/// ```rust -/// assert_eq!( -/// std::any::type_name::>(), -/// "core::option::Option", -/// ); -/// ``` #[stable(feature = "type_name", since = "1.38.0")] #[rustc_const_unstable(feature = "const_type_name")] pub const fn type_name() -> &'static str { diff --git a/src/libcore/array/mod.rs b/src/libcore/array.rs similarity index 98% rename from src/libcore/array/mod.rs rename to src/libcore/array.rs index 120658e9a4343..b5614010e5c2f 100644 --- a/src/libcore/array/mod.rs +++ b/src/libcore/array.rs @@ -14,13 +14,6 @@ use crate::hash::{Hash, self}; use crate::marker::Unsize; use crate::slice::{Iter, IterMut}; -#[cfg(not(bootstrap))] -mod iter; - -#[cfg(not(bootstrap))] -#[unstable(feature = "array_value_iter", issue = "0")] -pub use iter::IntoIter; - /// Utility trait implemented only on arrays of fixed size /// /// This trait can be used to implement other traits on fixed-size arrays diff --git a/src/libcore/array/iter.rs b/src/libcore/array/iter.rs deleted file mode 100644 index 850a599c6599f..0000000000000 --- a/src/libcore/array/iter.rs +++ /dev/null @@ -1,266 +0,0 @@ -//! Defines the `IntoIter` owned iterator for arrays. - -use crate::{ - fmt, - iter::{ExactSizeIterator, FusedIterator, TrustedLen}, - mem::{self, MaybeUninit}, - ops::Range, - ptr, -}; -use super::LengthAtMost32; - - -/// A by-value [array] iterator. -/// -/// [array]: ../../std/primitive.array.html -#[unstable(feature = "array_value_iter", issue = "0")] -pub struct IntoIter -where - [T; N]: LengthAtMost32, -{ - /// This is the array we are iterating over. - /// - /// Elements with index `i` where `alive.start <= i < alive.end` have not - /// been yielded yet and are valid array entries. Elements with indices `i - /// < alive.start` or `i >= alive.end` have been yielded already and must - /// not be accessed anymore! Those dead elements might even be in a - /// completely uninitialized state! - /// - /// So the invariants are: - /// - `data[alive]` is alive (i.e. contains valid elements) - /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the - /// elements were already read and must not be touched anymore!) - data: [MaybeUninit; N], - - /// The elements in `data` that have not been yielded yet. - /// - /// Invariants: - /// - `alive.start <= alive.end` - /// - `alive.end <= N` - alive: Range, -} - -impl IntoIter -where - [T; N]: LengthAtMost32, -{ - /// Creates a new iterator over the given `array`. - /// - /// *Note*: this method might never get stabilized and/or removed in the - /// future as there will likely be another, preferred way of obtaining this - /// iterator (either via `IntoIterator` for arrays or via another way). - #[unstable(feature = "array_value_iter", issue = "0")] - pub fn new(array: [T; N]) -> Self { - // The transmute here is actually safe. The docs of `MaybeUninit` - // promise: - // - // > `MaybeUninit` is guaranteed to have the same size and alignment - // > as `T`. - // - // The docs even show a transmute from an array of `MaybeUninit` to - // an array of `T`. - // - // With that, this initialization satisfies the invariants. - - // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it - // works with const generics: - // `mem::transmute::<[T; {N}], [MaybeUninit; {N}]>(array)` - // - // Until then, we do it manually here. We first create a bitwise copy - // but cast the pointer so that it is treated as a different type. Then - // we forget `array` so that it is not dropped. - let data = unsafe { - let data = ptr::read(&array as *const [T; N] as *const [MaybeUninit; N]); - mem::forget(array); - data - }; - - Self { - data, - alive: 0..N, - } - } - - /// Returns an immutable slice of all elements that have not been yielded - /// yet. - fn as_slice(&self) -> &[T] { - // This transmute is safe. As mentioned in `new`, `MaybeUninit` retains - // the size and alignment of `T`. Furthermore, we know that all - // elements within `alive` are properly initialized. - let slice = &self.data[self.alive.clone()]; - unsafe { - mem::transmute::<&[MaybeUninit], &[T]>(slice) - } - } -} - - -#[stable(feature = "array_value_iter_impls", since = "1.38.0")] -impl Iterator for IntoIter -where - [T; N]: LengthAtMost32, -{ - type Item = T; - fn next(&mut self) -> Option { - if self.alive.start == self.alive.end { - return None; - } - - // Bump start index. - // - // From the check above we know that `alive.start != alive.end`. - // Combine this with the invariant `alive.start <= alive.end`, we know - // that `alive.start < alive.end`. Increasing `alive.start` by 1 - // maintains the invariant regarding `alive`. However, due to this - // change, for a short time, the alive zone is not `data[alive]` - // anymore, but `data[idx..alive.end]`. - let idx = self.alive.start; - self.alive.start += 1; - - // Read the element from the array. This is safe: `idx` is an index - // into the "alive" region of the array. Reading this element means - // that `data[idx]` is regarded as dead now (i.e. do not touch). As - // `idx` was the start of the alive-zone, the alive zone is now - // `data[alive]` again, restoring all invariants. - let out = unsafe { self.data.get_unchecked(idx).read() }; - - Some(out) - } - - fn size_hint(&self) -> (usize, Option) { - let len = self.len(); - (len, Some(len)) - } - - fn count(self) -> usize { - self.len() - } - - fn last(mut self) -> Option { - self.next_back() - } -} - -#[stable(feature = "array_value_iter_impls", since = "1.38.0")] -impl DoubleEndedIterator for IntoIter -where - [T; N]: LengthAtMost32, -{ - fn next_back(&mut self) -> Option { - if self.alive.start == self.alive.end { - return None; - } - - // Decrease end index. - // - // From the check above we know that `alive.start != alive.end`. - // Combine this with the invariant `alive.start <= alive.end`, we know - // that `alive.start < alive.end`. As `alive.start` cannot be negative, - // `alive.end` is at least 1, meaning that we can safely decrement it - // by one. This also maintains the invariant `alive.start <= - // alive.end`. However, due to this change, for a short time, the alive - // zone is not `data[alive]` anymore, but `data[alive.start..alive.end - // + 1]`. - self.alive.end -= 1; - - // Read the element from the array. This is safe: `alive.end` is an - // index into the "alive" region of the array. Compare the previous - // comment that states that the alive region is - // `data[alive.start..alive.end + 1]`. Reading this element means that - // `data[alive.end]` is regarded as dead now (i.e. do not touch). As - // `alive.end` was the end of the alive-zone, the alive zone is now - // `data[alive]` again, restoring all invariants. - let out = unsafe { self.data.get_unchecked(self.alive.end).read() }; - - Some(out) - } -} - -#[stable(feature = "array_value_iter_impls", since = "1.38.0")] -impl Drop for IntoIter -where - [T; N]: LengthAtMost32, -{ - fn drop(&mut self) { - // We simply drop each element via `for_each`. This should not incur - // any significant runtime overhead and avoids adding another `unsafe` - // block. - self.by_ref().for_each(drop); - } -} - -#[stable(feature = "array_value_iter_impls", since = "1.38.0")] -impl ExactSizeIterator for IntoIter -where - [T; N]: LengthAtMost32, -{ - fn len(&self) -> usize { - // Will never underflow due to the invariant `alive.start <= - // alive.end`. - self.alive.end - self.alive.start - } - fn is_empty(&self) -> bool { - self.alive.is_empty() - } -} - -#[stable(feature = "array_value_iter_impls", since = "1.38.0")] -impl FusedIterator for IntoIter -where - [T; N]: LengthAtMost32, -{} - -// The iterator indeed reports the correct length. The number of "alive" -// elements (that will still be yielded) is the length of the range `alive`. -// This range is decremented in length in either `next` or `next_back`. It is -// always decremented by 1 in those methods, but only if `Some(_)` is returned. -#[stable(feature = "array_value_iter_impls", since = "1.38.0")] -unsafe impl TrustedLen for IntoIter -where - [T; N]: LengthAtMost32, -{} - -#[stable(feature = "array_value_iter_impls", since = "1.38.0")] -impl Clone for IntoIter -where - [T; N]: LengthAtMost32, -{ - fn clone(&self) -> Self { - unsafe { - // This creates a new uninitialized array. Note that the `assume_init` - // refers to the array, not the individual elements. And it is Ok if - // the array is in an uninitialized state as all elements may be - // uninitialized (all bit patterns are valid). Compare the - // `MaybeUninit` docs for more information. - let mut new_data: [MaybeUninit; N] = MaybeUninit::uninit().assume_init(); - - // Clone all alive elements. - for idx in self.alive.clone() { - // The element at `idx` in the old array is alive, so we can - // safely call `get_ref()`. We then clone it, and write the - // clone into the new array. - let clone = self.data.get_unchecked(idx).get_ref().clone(); - new_data.get_unchecked_mut(idx).write(clone); - } - - Self { - data: new_data, - alive: self.alive.clone(), - } - } - } -} - -#[stable(feature = "array_value_iter_impls", since = "1.38.0")] -impl fmt::Debug for IntoIter -where - [T; N]: LengthAtMost32, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Only print the elements that were not yielded yet: we cannot - // access the yielded elements anymore. - f.debug_tuple("IntoIter") - .field(&self.as_slice()) - .finish() - } -} diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index fda103a52d8bc..8579dbf353e80 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -229,6 +229,52 @@ pub struct Cell { value: UnsafeCell, } +impl Cell { + /// Returns a copy of the contained value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// let five = c.get(); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get(&self) -> T { + unsafe{ *self.value.get() } + } + + /// Updates the contained value using a function and returns the new value. + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_update)] + /// + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// let new = c.update(|x| x + 1); + /// + /// assert_eq!(new, 6); + /// assert_eq!(c.get(), 6); + /// ``` + #[inline] + #[unstable(feature = "cell_update", issue = "50186")] + pub fn update(&self, f: F) -> T + where + F: FnOnce(T) -> T, + { + let old = self.get(); + let new = f(old); + self.set(new); + new + } +} + #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for Cell where T: Send {} @@ -402,52 +448,6 @@ impl Cell { } } -impl Cell { - /// Returns a copy of the contained value. - /// - /// # Examples - /// - /// ``` - /// use std::cell::Cell; - /// - /// let c = Cell::new(5); - /// - /// let five = c.get(); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn get(&self) -> T { - unsafe{ *self.value.get() } - } - - /// Updates the contained value using a function and returns the new value. - /// - /// # Examples - /// - /// ``` - /// #![feature(cell_update)] - /// - /// use std::cell::Cell; - /// - /// let c = Cell::new(5); - /// let new = c.update(|x| x + 1); - /// - /// assert_eq!(new, 6); - /// assert_eq!(c.get(), 6); - /// ``` - #[inline] - #[unstable(feature = "cell_update", issue = "50186")] - pub fn update(&self, f: F) -> T - where - F: FnOnce(T) -> T, - { - let old = self.get(); - let new = f(old); - self.set(new); - new - } -} - impl Cell { /// Returns a raw pointer to the underlying data in this cell. /// diff --git a/src/libcore/char/convert.rs b/src/libcore/char/convert.rs index c456e14db12d4..0a870c67518c7 100644 --- a/src/libcore/char/convert.rs +++ b/src/libcore/char/convert.rs @@ -111,9 +111,11 @@ impl From for u32 { /// ``` /// use std::mem; /// - /// let c = 'c'; - /// let u = u32::from(c); - /// assert!(4 == mem::size_of_val(&u)) + /// fn main() { + /// let c = 'c'; + /// let u = u32::from(c); + /// assert!(4 == mem::size_of_val(&u)) + /// } /// ``` #[inline] fn from(c: char) -> Self { @@ -148,9 +150,11 @@ impl From for char { /// ``` /// use std::mem; /// - /// let u = 32 as u8; - /// let c = char::from(u); - /// assert!(4 == mem::size_of_val(&c)) + /// fn main() { + /// let u = 32 as u8; + /// let c = char::from(u); + /// assert!(4 == mem::size_of_val(&c)) + /// } /// ``` #[inline] fn from(i: u8) -> Self { diff --git a/src/libcore/char/decode.rs b/src/libcore/char/decode.rs index b71c9c2c40b37..23059243c61d7 100644 --- a/src/libcore/char/decode.rs +++ b/src/libcore/char/decode.rs @@ -31,23 +31,21 @@ pub struct DecodeUtf16Error { /// ``` /// use std::char::decode_utf16; /// -/// // 𝄞music -/// let v = [ -/// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834, -/// ]; +/// fn main() { +/// // 𝄞music +/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075, +/// 0x0073, 0xDD1E, 0x0069, 0x0063, +/// 0xD834]; /// -/// assert_eq!( -/// decode_utf16(v.iter().cloned()) -/// .map(|r| r.map_err(|e| e.unpaired_surrogate())) -/// .collect::>(), -/// vec![ -/// Ok('𝄞'), -/// Ok('m'), Ok('u'), Ok('s'), -/// Err(0xDD1E), -/// Ok('i'), Ok('c'), -/// Err(0xD834) -/// ] -/// ); +/// assert_eq!(decode_utf16(v.iter().cloned()) +/// .map(|r| r.map_err(|e| e.unpaired_surrogate())) +/// .collect::>(), +/// vec![Ok('𝄞'), +/// Ok('m'), Ok('u'), Ok('s'), +/// Err(0xDD1E), +/// Ok('i'), Ok('c'), +/// Err(0xD834)]); +/// } /// ``` /// /// A lossy decoder can be obtained by replacing `Err` results with the replacement character: @@ -55,17 +53,17 @@ pub struct DecodeUtf16Error { /// ``` /// use std::char::{decode_utf16, REPLACEMENT_CHARACTER}; /// -/// // 𝄞music -/// let v = [ -/// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834, -/// ]; +/// fn main() { +/// // 𝄞music +/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075, +/// 0x0073, 0xDD1E, 0x0069, 0x0063, +/// 0xD834]; /// -/// assert_eq!( -/// decode_utf16(v.iter().cloned()) -/// .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) -/// .collect::(), -/// "𝄞mus�ic�" -/// ); +/// assert_eq!(decode_utf16(v.iter().cloned()) +/// .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) +/// .collect::(), +/// "𝄞mus�ic�"); +/// } /// ``` #[stable(feature = "decode_utf16", since = "1.9.0")] #[inline] diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index 971d89e004446..a69eb0f6d4b20 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -116,9 +116,9 @@ impl char { // the code is split up here to improve execution speed for cases where // the `radix` is constant and 10 or smaller - let val = if radix <= 10 { + let val = if radix <= 10 { match self { - '0'..='9' => self as u32 - '0' as u32, + '0' ..= '9' => self as u32 - '0' as u32, _ => return None, } } else { @@ -130,11 +130,8 @@ impl char { } }; - if val < radix { - Some(val) - } else { - None - } + if val < radix { Some(val) } + else { None } } /// Returns an iterator that yields the hexadecimal Unicode escape of a @@ -306,8 +303,8 @@ impl char { '\r' => EscapeDefaultState::Backslash('r'), '\n' => EscapeDefaultState::Backslash('n'), '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self), - '\x20'..='\x7e' => EscapeDefaultState::Char(self), - _ => EscapeDefaultState::Unicode(self.escape_unicode()), + '\x20' ..= '\x7e' => EscapeDefaultState::Char(self), + _ => EscapeDefaultState::Unicode(self.escape_unicode()) }; EscapeDefault { state: init_state } } @@ -439,31 +436,30 @@ impl char { pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str { let code = self as u32; unsafe { - let len = if code < MAX_ONE_B && !dst.is_empty() { + let len = + if code < MAX_ONE_B && !dst.is_empty() { *dst.get_unchecked_mut(0) = code as u8; 1 } else if code < MAX_TWO_B && dst.len() >= 2 { *dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; *dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT; 2 - } else if code < MAX_THREE_B && dst.len() >= 3 { + } else if code < MAX_THREE_B && dst.len() >= 3 { *dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; - *dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT; *dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT; 3 } else if dst.len() >= 4 { *dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; *dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT; - *dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT; *dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT; 4 } else { - panic!( - "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}", + panic!("encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}", from_u32_unchecked(code).len_utf8(), code, - dst.len(), - ) + dst.len()) }; from_utf8_unchecked_mut(dst.get_unchecked_mut(..len)) } @@ -519,24 +515,15 @@ impl char { *dst.get_unchecked_mut(1) = 0xDC00 | ((code as u16) & 0x3FF); slice::from_raw_parts_mut(dst.as_mut_ptr(), 2) } else { - panic!( - "encode_utf16: need {} units to encode U+{:X}, but the buffer has {}", + panic!("encode_utf16: need {} units to encode U+{:X}, but the buffer has {}", from_u32_unchecked(code).len_utf16(), code, - dst.len(), - ) + dst.len()) } } } - /// Returns `true` if this `char` has the `Alphabetic` property. - /// - /// `Alphabetic` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and - /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. - /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ - /// [ucd]: https://www.unicode.org/reports/tr44/ - /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt + /// Returns `true` if this `char` is an alphabetic code point, and false if not. /// /// # Examples /// @@ -560,14 +547,10 @@ impl char { } } - /// Returns `true` if this `char` has the `Lowercase` property. + /// Returns `true` if this `char` is lowercase. /// - /// `Lowercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and - /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. - /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ - /// [ucd]: https://www.unicode.org/reports/tr44/ - /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt + /// 'Lowercase' is defined according to the terms of the Unicode Derived Core + /// Property `Lowercase`. /// /// # Examples /// @@ -592,14 +575,10 @@ impl char { } } - /// Returns `true` if this `char` has the `Uppercase` property. - /// - /// `Uppercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and - /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// Returns `true` if this `char` is uppercase. /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ - /// [ucd]: https://www.unicode.org/reports/tr44/ - /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt + /// 'Uppercase' is defined according to the terms of the Unicode Derived Core + /// Property `Uppercase`. /// /// # Examples /// @@ -624,12 +603,10 @@ impl char { } } - /// Returns `true` if this `char` has the `White_Space` property. + /// Returns `true` if this `char` is whitespace. /// - /// `White_Space` is specified in the [Unicode Character Database][ucd] [`PropList.txt`]. - /// - /// [ucd]: https://www.unicode.org/reports/tr44/ - /// [`PropList.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt + /// 'Whitespace' is defined according to the terms of the Unicode Derived Core + /// Property `White_Space`. /// /// # Examples /// @@ -653,10 +630,10 @@ impl char { } } - /// Returns `true` if this `char` satisfies either [`is_alphabetic()`] or [`is_numeric()`]. + /// Returns `true` if this `char` is alphanumeric. /// - /// [`is_alphabetic()`]: #method.is_alphabetic - /// [`is_numeric()`]: #method.is_numeric + /// 'Alphanumeric'-ness is defined in terms of the Unicode General Categories + /// `Nd`, `Nl`, `No` and the Derived Core Property `Alphabetic`. /// /// # Examples /// @@ -678,15 +655,10 @@ impl char { self.is_alphabetic() || self.is_numeric() } - /// Returns `true` if this `char` has the general category for control codes. - /// - /// Control codes (code points with the general category of `Cc`) are described in Chapter 4 - /// (Character Properties) of the [Unicode Standard] and specified in the [Unicode Character - /// Database][ucd] [`UnicodeData.txt`]. + /// Returns `true` if this `char` is a control code point. /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ - /// [ucd]: https://www.unicode.org/reports/tr44/ - /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// 'Control code point' is defined in terms of the Unicode General + /// Category `Cc`. /// /// # Examples /// @@ -703,29 +675,19 @@ impl char { general_category::Cc(self) } - /// Returns `true` if this `char` has the `Grapheme_Extend` property. + /// Returns `true` if this `char` is an extended grapheme character. /// - /// `Grapheme_Extend` is described in [Unicode Standard Annex #29 (Unicode Text - /// Segmentation)][uax29] and specified in the [Unicode Character Database][ucd] - /// [`DerivedCoreProperties.txt`]. - /// - /// [uax29]: https://www.unicode.org/reports/tr29/ - /// [ucd]: https://www.unicode.org/reports/tr44/ - /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt + /// 'Extended grapheme character' is defined in terms of the Unicode Shaping and Rendering + /// Category `Grapheme_Extend`. #[inline] pub(crate) fn is_grapheme_extended(self) -> bool { derived_property::Grapheme_Extend(self) } - /// Returns `true` if this `char` has one of the general categories for numbers. - /// - /// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric - /// characters, and `No` for other numeric characters) are specified in the [Unicode Character - /// Database][ucd] [`UnicodeData.txt`]. + /// Returns `true` if this `char` is numeric. /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ - /// [ucd]: https://www.unicode.org/reports/tr44/ - /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// 'Numeric'-ness is defined in terms of the Unicode General Categories + /// `Nd`, `Nl`, `No`. /// /// # Examples /// @@ -751,29 +713,25 @@ impl char { } } - /// Returns an iterator that yields the lowercase mapping of this `char` as one or more - /// `char`s. + /// Returns an iterator that yields the lowercase equivalent of a `char` + /// as one or more `char`s. /// - /// If this `char` does not have a lowercase mapping, the iterator yields the same `char`. + /// If a character does not have a lowercase equivalent, the same character + /// will be returned back by the iterator. /// - /// If this `char` has a one-to-one lowercase mapping given by the [Unicode Character - /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`. + /// This performs complex unconditional mappings with no tailoring: it maps + /// one Unicode character to its lowercase equivalent according to the + /// [Unicode database] and the additional complex mappings + /// [`SpecialCasing.txt`]. Conditional mappings (based on context or + /// language) are not considered here. /// - /// [ucd]: https://www.unicode.org/reports/tr44/ - /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// For a full reference, see [here][reference]. /// - /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields - /// the `char`(s) given by [`SpecialCasing.txt`]. + /// [Unicode database]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt /// - /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt + /// [`SpecialCasing.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt /// - /// This operation performs an unconditional mapping without tailoring. That is, the conversion - /// is independent of context and language. - /// - /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in - /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion. - /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [reference]: http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 /// /// # Examples /// @@ -816,29 +774,25 @@ impl char { ToLowercase(CaseMappingIter::new(conversions::to_lower(self))) } - /// Returns an iterator that yields the uppercase mapping of this `char` as one or more - /// `char`s. - /// - /// If this `char` does not have a uppercase mapping, the iterator yields the same `char`. - /// - /// If this `char` has a one-to-one uppercase mapping given by the [Unicode Character - /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`. + /// Returns an iterator that yields the uppercase equivalent of a `char` + /// as one or more `char`s. /// - /// [ucd]: https://www.unicode.org/reports/tr44/ - /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// If a character does not have an uppercase equivalent, the same character + /// will be returned back by the iterator. /// - /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields - /// the `char`(s) given by [`SpecialCasing.txt`]. + /// This performs complex unconditional mappings with no tailoring: it maps + /// one Unicode character to its uppercase equivalent according to the + /// [Unicode database] and the additional complex mappings + /// [`SpecialCasing.txt`]. Conditional mappings (based on context or + /// language) are not considered here. /// - /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt + /// For a full reference, see [here][reference]. /// - /// This operation performs an unconditional mapping without tailoring. That is, the conversion - /// is independent of context and language. + /// [Unicode database]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt /// - /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in - /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion. + /// [`SpecialCasing.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [reference]: http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 /// /// # Examples /// diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index 0ea4187ccd482..eda0e7c518c58 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -49,10 +49,8 @@ impl fmt::Debug for c_void { /// Basic implementation of a `va_list`. // The name is WIP, using `VaListImpl` for now. #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), + not(target_arch = "x86_64"), not(target_arch = "asmjs")), all(target_arch = "aarch64", target_os = "ios"), - target_arch = "wasm32", - target_arch = "asmjs", windows))] #[repr(transparent)] #[unstable(feature = "c_variadic", @@ -69,10 +67,8 @@ pub struct VaListImpl<'f> { } #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), + not(target_arch = "x86_64"), not(target_arch = "asmjs")), all(target_arch = "aarch64", target_os = "ios"), - target_arch = "wasm32", - target_arch = "asmjs", windows))] #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ @@ -141,6 +137,38 @@ pub struct VaListImpl<'f> { _marker: PhantomData<&'f mut &'f c_void>, } +/// asm.js ABI implementation of a `va_list`. +// asm.js uses the PNaCl ABI, which specifies that a `va_list` is +// an array of 4 32-bit integers, according to the old PNaCl docs at +// https://web.archive.org/web/20130518054430/https://www.chromium.org/nativeclient/pnacl/bitcode-abi#TOC-Derived-Types +// and clang does the same in `CreatePNaClABIBuiltinVaListDecl` from `lib/AST/ASTContext.cpp` +#[cfg(all(target_arch = "asmjs", not(windows)))] +#[repr(C)] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +#[lang = "va_list"] +pub struct VaListImpl<'f> { + inner: [crate::mem::MaybeUninit; 4], + _marker: PhantomData<&'f mut &'f c_void>, +} + +#[cfg(all(target_arch = "asmjs", not(windows)))] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +impl<'f> fmt::Debug for VaListImpl<'f> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + unsafe { + write!(f, "va_list* [{:#x}, {:#x}, {:#x}, {:#x}]", + self.inner[0].read(), self.inner[1].read(), + self.inner[2].read(), self.inner[3].read()) + } + } +} + /// A wrapper for a `va_list` #[repr(transparent)] #[derive(Debug)] @@ -150,18 +178,14 @@ pub struct VaListImpl<'f> { issue = "44930")] pub struct VaList<'a, 'f: 'a> { #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), + not(target_arch = "x86_64"), not(target_arch = "asmjs")), all(target_arch = "aarch64", target_os = "ios"), - target_arch = "wasm32", - target_arch = "asmjs", windows))] inner: VaListImpl<'f>, #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", - target_arch = "x86_64"), + target_arch = "x86_64", target_arch = "asmjs"), any(not(target_arch = "aarch64"), not(target_os = "ios")), - not(target_arch = "wasm32"), - not(target_arch = "asmjs"), not(windows)))] inner: &'a mut VaListImpl<'f>, @@ -169,10 +193,8 @@ pub struct VaList<'a, 'f: 'a> { } #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), + not(target_arch = "x86_64"), not(target_arch = "asmjs")), all(target_arch = "aarch64", target_os = "ios"), - target_arch = "wasm32", - target_arch = "asmjs", windows))] #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ @@ -190,10 +212,8 @@ impl<'f> VaListImpl<'f> { } #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", - target_arch = "x86_64"), + target_arch = "x86_64", target_arch = "asmjs"), any(not(target_arch = "aarch64"), not(target_os = "ios")), - not(target_arch = "wasm32"), - not(target_arch = "asmjs"), not(windows)))] #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index e6e3454b36f81..15ce2277fa00d 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -775,10 +775,10 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { reason = "recently added", issue = "62482")] pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> { - self.result = self.result.and_then(|_| { - assert!(!self.has_key, "attempted to begin a new map entry \ - without completing the previous one"); + assert!(!self.has_key, "attempted to begin a new map entry \ + without completing the previous one"); + self.result = self.result.and_then(|_| { if self.is_pretty() { if !self.has_fields { self.fmt.write_str("\n")?; @@ -839,9 +839,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { reason = "recently added", issue = "62482")] pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> { - self.result = self.result.and_then(|_| { - assert!(self.has_key, "attempted to format a map value before its key"); + assert!(self.has_key, "attempted to format a map value before its key"); + self.result = self.result.and_then(|_| { if self.is_pretty() { let mut slot = None; let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut self.state); @@ -924,11 +924,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn finish(&mut self) -> fmt::Result { - self.result.and_then(|_| { - assert!(!self.has_key, "attempted to finish a map with a partial entry"); + assert!(!self.has_key, "attempted to finish a map with a partial entry"); - self.fmt.write_str("}") - }) + self.result.and_then(|_| self.fmt.write_str("}")) } fn is_pretty(&self) -> bool { diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 0e83a282b18f7..aafa35873bb65 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -108,10 +108,10 @@ pub struct Error; /// [`io::Write`]: ../../std/io/trait.Write.html #[stable(feature = "rust1", since = "1.0.0")] pub trait Write { - /// Writes a string slice into this writer, returning whether the write + /// Writes a slice of bytes into this writer, returning whether the write /// succeeded. /// - /// This method can only succeed if the entire string slice was successfully + /// This method can only succeed if the entire byte slice was successfully /// written, and this method will not return until all data has been /// written or an error occurs. /// @@ -1532,10 +1532,12 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// assert_eq!(&format!("{:<}", Foo), "left"); - /// assert_eq!(&format!("{:>}", Foo), "right"); - /// assert_eq!(&format!("{:^}", Foo), "center"); - /// assert_eq!(&format!("{}", Foo), "into the void"); + /// fn main() { + /// assert_eq!(&format!("{:<}", Foo), "left"); + /// assert_eq!(&format!("{:>}", Foo), "right"); + /// assert_eq!(&format!("{:^}", Foo), "center"); + /// assert_eq!(&format!("{}", Foo), "into the void"); + /// } /// ``` #[stable(feature = "fmt_flags_align", since = "1.28.0")] pub fn align(&self) -> Option { @@ -2025,7 +2027,7 @@ impl Pointer for *const T { if f.alternate() { f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32); - if f.width.is_none() { + if let None = f.width { f.width = Some(((mem::size_of::() * 8) / 4) + 2); } } diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index 368a2f16b281e..ee4be6c915119 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -114,8 +114,24 @@ pub fn black_box(dummy: T) -> T { // this. LLVM's intepretation of inline assembly is that it's, well, a black // box. This isn't the greatest implementation since it probably deoptimizes // more than we want, but it's so far good enough. + #[cfg(not(any( + target_arch = "asmjs", + all( + target_arch = "wasm32", + target_os = "emscripten" + ) + )))] unsafe { asm!("" : : "r"(&dummy)); return dummy; } + + // Not all platforms support inline assembly so try to do something without + // inline assembly which in theory still hinders at least some optimizations + // on those targets. This is the "best effort" scenario. + unsafe { + let ret = crate::ptr::read_volatile(&dummy); + crate::mem::forget(dummy); + ret + } } diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs index 00a864170583e..25439136b8538 100644 --- a/src/libcore/iter/traits/collect.rs +++ b/src/libcore/iter/traits/collect.rs @@ -167,7 +167,7 @@ pub trait FromIterator: Sized { /// // and we'll implement IntoIterator /// impl IntoIterator for MyCollection { /// type Item = i32; -/// type IntoIter = std::vec::IntoIter; +/// type IntoIter = ::std::vec::IntoIter; /// /// fn into_iter(self) -> Self::IntoIter { /// self.0.into_iter() diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index a272035150a15..0a9e076ec5869 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -1859,13 +1859,14 @@ pub trait Iterator { Self: Sized, F: FnMut(Self::Item) -> bool { #[inline] - fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> LoopState<(), ()> { - move |(), x| { + fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> { + move |x| { if f(x) { LoopState::Continue(()) } else { LoopState::Break(()) } } } - self.try_fold((), check(f)) == LoopState::Continue(()) + + self.try_for_each(check(f)) == LoopState::Continue(()) } /// Tests if any element of the iterator matches a predicate. @@ -1912,14 +1913,14 @@ pub trait Iterator { F: FnMut(Self::Item) -> bool { #[inline] - fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> LoopState<(), ()> { - move |(), x| { + fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> { + move |x| { if f(x) { LoopState::Break(()) } else { LoopState::Continue(()) } } } - self.try_fold((), check(f)) == LoopState::Break(()) + self.try_for_each(check(f)) == LoopState::Break(()) } /// Searches for an element of an iterator that satisfies a predicate. @@ -1971,16 +1972,14 @@ pub trait Iterator { P: FnMut(&Self::Item) -> bool, { #[inline] - fn check( - mut predicate: impl FnMut(&T) -> bool - ) -> impl FnMut((), T) -> LoopState<(), T> { - move |(), x| { + 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_fold((), check(predicate)).break_value() + self.try_for_each(check(predicate)).break_value() } /// Applies function to the elements of iterator and returns @@ -2005,14 +2004,14 @@ pub trait Iterator { F: FnMut(Self::Item) -> Option, { #[inline] - fn check(mut f: impl FnMut(T) -> Option) -> impl FnMut((), T) -> LoopState<(), B> { - move |(), x| match f(x) { + 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(()), } } - self.try_fold((), check(f)).break_value() + self.try_for_each(check(f)).break_value() } /// Searches for an element in an iterator, returning its index. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 0819969b93360..e8c76b49a8e56 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -121,12 +121,13 @@ #![feature(hexagon_target_feature)] #![feature(const_int_conversion)] #![feature(const_transmute)] -#![cfg_attr(bootstrap, feature(non_exhaustive))] +#![feature(non_exhaustive)] #![feature(structural_match)] #![feature(abi_unadjusted)] #![feature(adx_target_feature)] #![feature(maybe_uninit_slice)] #![feature(external_doc)] +#![feature(mem_take)] #![feature(associated_type_bounds)] #[prelude_import] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 35558e3abcddd..ef91c3559d8be 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -238,33 +238,6 @@ macro_rules! debug_assert_ne { ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); }) } -/// Returns whether the given expression matches any of the given patterns. -/// -/// Like in a `match` expression, the pattern can be optionally followed by `if` -/// and a guard expression that has access to names bound by the pattern. -/// -/// # Examples -/// -/// ``` -/// #![feature(matches_macro)] -/// -/// let foo = 'f'; -/// assert!(matches!(foo, 'A'..='Z' | 'a'..='z')); -/// -/// let bar = Some(4); -/// assert!(matches!(bar, Some(x) if x > 2)); -/// ``` -#[macro_export] -#[unstable(feature = "matches_macro", issue = "65721")] -macro_rules! matches { - ($expression:expr, $( $pattern:pat )|+ $( if $guard: expr )?) => { - match $expression { - $( $pattern )|+ $( if $guard )? => true, - _ => false - } - } -} - /// Unwraps a result or propagates its error. /// /// The `?` operator was added to replace `try!` and should be used instead. @@ -492,7 +465,7 @@ macro_rules! writeln { /// The unsafe counterpart of this macro is the [`unreachable_unchecked`] function, which /// will cause undefined behavior if the code is reached. /// -/// [`panic!`]: ../std/macro.panic.html +/// [`panic!`]: ../std/macro.panic.html /// [`unreachable_unchecked`]: ../std/hint/fn.unreachable_unchecked.html /// [`std::hint`]: ../std/hint/index.html /// @@ -501,7 +474,6 @@ macro_rules! writeln { /// This will always [`panic!`] /// /// [`panic!`]: ../std/macro.panic.html -/// /// # Examples /// /// Match arms: @@ -547,20 +519,15 @@ macro_rules! unreachable { }); } -/// Indicates unfinished code by panicking with a message of "not yet implemented". -/// -/// This allows the your code to type-check, which is useful if you are prototyping or -/// implementing a trait that requires multiple methods which you don't plan of using all of. +/// Indicates unfinished code. /// -/// There is no difference between `unimplemented!` and `todo!` apart from the -/// name. +/// This can be useful if you are prototyping and are just looking to have your +/// code type-check, or if you're implementing a trait that requires multiple +/// methods, and you're only planning on using one of them. /// /// # Panics /// -/// This will always [panic!](macro.panic.html) because `unimplemented!` is just a -/// shorthand for `panic!` with a fixed, specific message. -/// -/// Like `panic!`, this macro has a second form for displaying custom values. +/// This will always [panic!](macro.panic.html) /// /// # Examples /// @@ -568,53 +535,38 @@ macro_rules! unreachable { /// /// ``` /// trait Foo { -/// fn bar(&self) -> u8; +/// fn bar(&self); /// fn baz(&self); -/// fn qux(&self) -> Result; /// } /// ``` /// -/// We want to implement `Foo` for 'MyStruct', but so far we only know how to -/// implement the `bar()` function. `baz()` and `qux()` will still need to be defined -/// in our implementation of `Foo`, but we can use `unimplemented!` in their definitions -/// to allow our code to compile. -/// -/// In the meantime, we want to have our program stop running once these -/// unimplemented functions are reached. +/// We want to implement `Foo` on one of our types, but we also want to work on +/// just `bar()` first. In order for our code to compile, we need to implement +/// `baz()`, so we can use `unimplemented!`: /// /// ``` /// # trait Foo { -/// # fn bar(&self) -> u8; +/// # fn bar(&self); /// # fn baz(&self); -/// # fn qux(&self) -> Result; /// # } /// struct MyStruct; /// /// impl Foo for MyStruct { -/// fn bar(&self) -> u8 { -/// 1 + 1 +/// fn bar(&self) { +/// // implementation goes here /// } /// /// fn baz(&self) { -/// // We aren't sure how to even start writing baz yet, -/// // so we have no logic here at all. -/// // This will display "thread 'main' panicked at 'not yet implemented'". +/// // let's not worry about implementing baz() for now /// unimplemented!(); /// } -/// -/// fn qux(&self) -> Result { -/// let n = self.bar(); -/// // We have some logic here, -/// // so we can use unimplemented! to display what we have so far. -/// // This will display: -/// // "thread 'main' panicked at 'not yet implemented: we need to divide by 2'". -/// unimplemented!("we need to divide by {}", n); -/// } /// } /// /// fn main() { /// let s = MyStruct; /// s.bar(); +/// +/// // we aren't even using baz() yet, so this is fine. /// } /// ``` #[macro_export] @@ -627,10 +579,8 @@ macro_rules! unimplemented { /// Indicates unfinished code. /// /// This can be useful if you are prototyping and are just looking to have your -/// code typecheck. -/// -/// There is no difference between `unimplemented!` and `todo!` apart from the -/// name. +/// code typecheck. `todo!` works exactly like `unimplemented!`. The only +/// difference between the two macros is the name. /// /// # Panics /// @@ -652,6 +602,8 @@ macro_rules! unimplemented { /// `baz()`, so we can use `todo!`: /// /// ``` +/// #![feature(todo_macro)] +/// /// # trait Foo { /// # fn bar(&self); /// # fn baz(&self); @@ -677,7 +629,7 @@ macro_rules! unimplemented { /// } /// ``` #[macro_export] -#[stable(feature = "todo_macro", since = "1.39.0")] +#[unstable(feature = "todo_macro", issue = "59277")] macro_rules! todo { () => (panic!("not yet implemented")); ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+))); diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index c7da56aad309a..8767625d4ed37 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -236,7 +236,7 @@ pub fn forget_unsized(t: T) { /// ``` /// /// [alignment]: ./fn.align_of.html -#[inline(always)] +#[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] pub const fn size_of() -> usize { @@ -328,7 +328,7 @@ pub fn min_align_of_val(val: &T) -> usize { /// /// assert_eq!(4, mem::align_of::()); /// ``` -#[inline(always)] +#[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] pub const fn align_of() -> usize { @@ -368,17 +368,15 @@ pub fn align_of_val(val: &T) -> usize { /// make a difference in release builds (where a loop that has no side-effects /// is easily detected and eliminated), but is often a big win for debug builds. /// -/// Note that [`drop_in_place`] already performs this check, so if your workload -/// can be reduced to some small number of [`drop_in_place`] calls, using this is -/// unnecessary. In particular note that you can [`drop_in_place`] a slice, and that +/// Note that `ptr::drop_in_place` already performs this check, so if your workload +/// can be reduced to some small number of drop_in_place calls, using this is +/// unnecessary. In particular note that you can drop_in_place a slice, and that /// will do a single needs_drop check for all the values. /// /// Types like Vec therefore just `drop_in_place(&mut self[..])` without using -/// `needs_drop` explicitly. Types like [`HashMap`], on the other hand, have to drop +/// needs_drop explicitly. Types like `HashMap`, on the other hand, have to drop /// values one at a time and should use this API. /// -/// [`drop_in_place`]: ../ptr/fn.drop_in_place.html -/// [`HashMap`]: ../../std/collections/struct.HashMap.html /// /// # Examples /// @@ -520,6 +518,8 @@ pub fn swap(x: &mut T, y: &mut T) { /// A simple example: /// /// ``` +/// #![feature(mem_take)] +/// /// use std::mem; /// /// let mut v: Vec = vec![1, 2]; @@ -550,6 +550,8 @@ pub fn swap(x: &mut T, y: &mut T) { /// `self`, allowing it to be returned: /// /// ``` +/// #![feature(mem_take)] +/// /// use std::mem; /// /// # struct Buffer { buf: Vec } @@ -568,7 +570,7 @@ pub fn swap(x: &mut T, y: &mut T) { /// /// [`Clone`]: ../../std/clone/trait.Clone.html #[inline] -#[stable(feature = "mem_take", since = "1.40.0")] +#[unstable(feature = "mem_take", issue = "61129")] pub fn take(dest: &mut T) -> T { replace(dest, T::default()) } diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs index ed89852dc48da..fa3c8075378ca 100644 --- a/src/libcore/num/dec2flt/algorithm.rs +++ b/src/libcore/num/dec2flt/algorithm.rs @@ -143,12 +143,13 @@ pub fn fast_path(integral: &[u8], fractional: &[u8], e: i64) -> Opt /// > not a bound for the true error, but bounds the difference between the approximation z and /// > the best possible approximation that uses p bits of significand.) pub fn bellerophon(f: &Big, e: i16) -> T { - let slop = if f <= &Big::from_u64(T::MAX_SIG) { + let slop; + if f <= &Big::from_u64(T::MAX_SIG) { // The cases abs(e) < log5(2^N) are in fast_path() - if e >= 0 { 0 } else { 3 } + slop = if e >= 0 { 0 } else { 3 }; } else { - if e >= 0 { 1 } else { 4 } - }; + slop = if e >= 0 { 1 } else { 4 }; + } let z = rawfp::big_to_fp(f).mul(&power_of_ten(e)).normalize(); let exp_p_n = 1 << (P - T::SIG_BITS as u32); let lowbits: i64 = (z.f % exp_p_n) as i64; diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index b4ade70414462..933a2a124733b 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -252,7 +252,7 @@ Basic usage: $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[inline(always)] + #[inline] #[rustc_promotable] pub const fn min_value() -> Self { !0 ^ ((!0 as $UnsignedT) >> 1) as Self @@ -271,7 +271,7 @@ Basic usage: $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[inline(always)] + #[inline] #[rustc_promotable] pub const fn max_value() -> Self { !Self::min_value() @@ -938,9 +938,7 @@ Basic usage: ``` ", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101); assert_eq!(", stringify!($SelfT), "::max_value().saturating_add(100), ", stringify!($SelfT), -"::max_value()); -assert_eq!(", stringify!($SelfT), "::min_value().saturating_add(-1), ", stringify!($SelfT), -"::min_value());", +"::max_value());", $EndFeature, " ```"), @@ -954,6 +952,7 @@ $EndFeature, " } } + doc_comment! { concat!("Saturating integer subtraction. Computes `self - rhs`, saturating at the numeric bounds instead of overflowing. @@ -965,9 +964,7 @@ Basic usage: ``` ", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_sub(127), -27); assert_eq!(", stringify!($SelfT), "::min_value().saturating_sub(100), ", stringify!($SelfT), -"::min_value()); -assert_eq!(", stringify!($SelfT), "::max_value().saturating_sub(-1), ", stringify!($SelfT), -"::max_value());", +"::min_value());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] @@ -1058,7 +1055,7 @@ $EndFeature, " #[inline] pub fn saturating_mul(self, rhs: Self) -> Self { self.checked_mul(rhs).unwrap_or_else(|| { - if (self < 0) == (rhs < 0) { + if (self < 0 && rhs < 0) || (self > 0 && rhs > 0) { Self::max_value() } else { Self::min_value() @@ -1864,7 +1861,7 @@ if `self < 0`, this is equal to round towards +/- infinity. # Panics -This function will panic if `rhs` is 0 or the division results in overflow. +This function will panic if `rhs` is 0. # Examples @@ -1903,7 +1900,7 @@ This is done as if by the Euclidean division algorithm -- given # Panics -This function will panic if `rhs` is 0 or the division results in overflow. +This function will panic if `rhs` is 0. # Examples @@ -2311,7 +2308,7 @@ Basic usage: ```"), #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] - #[inline(always)] + #[inline] pub const fn min_value() -> Self { 0 } } @@ -2328,7 +2325,7 @@ stringify!($MaxV), ");", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] - #[inline(always)] + #[inline] pub const fn max_value() -> Self { !0 } } @@ -3694,10 +3691,6 @@ Since, for the positive integers, all common definitions of division are equal, this is exactly equal to `self / rhs`. -# Panics - -This function will panic if `rhs` is 0. - # Examples Basic usage: @@ -3723,10 +3716,6 @@ Since, for the positive integers, all common definitions of division are equal, this is exactly equal to `self % rhs`. -# Panics - -This function will panic if `rhs` is 0. - # Examples Basic usage: @@ -3757,8 +3746,8 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub const fn is_power_of_two(self) -> bool { - self.count_ones() == 1 + pub fn is_power_of_two(self) -> bool { + (self.wrapping_sub(1)) & self == 0 && !(self == 0) } } diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index 5fe9895d8d24f..59a10ae99bb6a 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -437,7 +437,7 @@ assert_eq!(n.trailing_zeros(), 3); /// wrapping the truncated bits to the end of the resulting /// integer. /// - /// Please note this isn't the same operation as the `<<` shifting + /// Please note this isn't the same operation as the `>>` shifting /// operator! /// /// # Examples @@ -463,7 +463,7 @@ assert_eq!(n.trailing_zeros(), 3); /// wrapping the truncated bits to the beginning of the resulting /// integer. /// - /// Please note this isn't the same operation as the `>>` shifting + /// Please note this isn't the same operation as the `<<` shifting /// operator! /// /// # Examples diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs index d29147645f7ef..8e46830084642 100644 --- a/src/libcore/ops/unsize.rs +++ b/src/libcore/ops/unsize.rs @@ -76,7 +76,7 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} /// ``` /// # #![feature(dispatch_from_dyn, unsize)] /// # use std::{ops::DispatchFromDyn, marker::Unsize}; -/// # struct Rc(std::rc::Rc); +/// # struct Rc(::std::rc::Rc); /// impl DispatchFromDyn> for Rc /// where /// T: Unsize, diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 89f2d7ab29c93..5569d99f8d81d 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -46,7 +46,7 @@ //! # Options and pointers ("nullable" pointers) //! //! Rust's pointer types must always point to a valid location; there are -//! no "null" references. Instead, Rust has *optional* pointers, like +//! no "null" pointers. Instead, Rust has *optional* pointers, like //! the optional owned box, [`Option`]`<`[`Box`]`>`. //! //! The following example uses [`Option`] to create an optional box of @@ -64,7 +64,7 @@ //! //! fn check_optional(optional: Option>) { //! match optional { -//! Some(p) => println!("has value {}", p), +//! Some(ref p) => println!("has value {}", p), //! None => println!("has no value"), //! } //! } @@ -83,7 +83,7 @@ //! let msg = Some("howdy"); //! //! // Take a reference to the contained string -//! if let Some(m) = &msg { +//! if let Some(ref m) = msg { //! println!("{}", *m); //! } //! @@ -395,10 +395,10 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_or(self, default: T) -> T { + pub fn unwrap_or(self, def: T) -> T { match self { Some(x) => x, - None => default, + None => def, } } @@ -837,8 +837,9 @@ impl Option { #[inline] #[stable(feature = "option_entry", since = "1.20.0")] pub fn get_or_insert_with T>(&mut self, f: F) -> &mut T { - if let None = *self { - *self = Some(f()); + match *self { + None => *self = Some(f()), + _ => (), } match *self { @@ -1101,6 +1102,7 @@ impl Option { } } +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] impl Option { /// Converts from `Option` (or `&Option`) to `Option<&T::Target>`. /// @@ -1112,18 +1114,20 @@ impl Option { /// # 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); /// ``` - #[stable(feature = "option_deref", since = "1.40.0")] pub fn as_deref(&self) -> Option<&T::Target> { self.as_ref().map(|t| t.deref()) } } +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] impl Option { /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. /// @@ -1133,13 +1137,14 @@ impl Option { /// # 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())); /// ``` - #[stable(feature = "option_deref", since = "1.40.0")] pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> { self.as_mut().map(|t| t.deref_mut()) } diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 3cc0a1cd75e88..13ccc9b252a77 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -188,7 +188,7 @@ unsafe fn real_drop_in_place(to_drop: &mut T) { /// let p: *const i32 = ptr::null(); /// assert!(p.is_null()); /// ``` -#[inline(always)] +#[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] pub const fn null() -> *const T { 0 as *const T } @@ -203,7 +203,7 @@ pub const fn null() -> *const T { 0 as *const T } /// let p: *mut i32 = ptr::null_mut(); /// assert!(p.is_null()); /// ``` -#[inline(always)] +#[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] pub const fn null_mut() -> *mut T { 0 as *mut T } @@ -2732,29 +2732,31 @@ impl Eq for *mut T {} /// impl Trait for Wrapper {} /// impl Trait for i32 {} /// -/// let wrapper = Wrapper { member: 10 }; -/// -/// // Pointers have equal addresses. -/// assert!(std::ptr::eq( -/// &wrapper as *const Wrapper as *const u8, -/// &wrapper.member as *const i32 as *const u8 -/// )); -/// -/// // Objects have equal addresses, but `Trait` has different implementations. -/// assert!(!std::ptr::eq( -/// &wrapper as &dyn Trait, -/// &wrapper.member as &dyn Trait, -/// )); -/// assert!(!std::ptr::eq( -/// &wrapper as &dyn Trait as *const dyn Trait, -/// &wrapper.member as &dyn Trait as *const dyn Trait, -/// )); -/// -/// // Converting the reference to a `*const u8` compares by address. -/// assert!(std::ptr::eq( -/// &wrapper as &dyn Trait as *const dyn Trait as *const u8, -/// &wrapper.member as &dyn Trait as *const dyn Trait as *const u8, -/// )); +/// fn main() { +/// let wrapper = Wrapper { member: 10 }; +/// +/// // Pointers have equal addresses. +/// assert!(std::ptr::eq( +/// &wrapper as *const Wrapper as *const u8, +/// &wrapper.member as *const i32 as *const u8 +/// )); +/// +/// // Objects have equal addresses, but `Trait` has different implementations. +/// assert!(!std::ptr::eq( +/// &wrapper as &dyn Trait, +/// &wrapper.member as &dyn Trait, +/// )); +/// assert!(!std::ptr::eq( +/// &wrapper as &dyn Trait as *const dyn Trait, +/// &wrapper.member as &dyn Trait as *const dyn Trait, +/// )); +/// +/// // Converting the reference to a `*const u8` compares by address. +/// assert!(std::ptr::eq( +/// &wrapper as &dyn Trait as *const dyn Trait as *const u8, +/// &wrapper.member as &dyn Trait as *const dyn Trait as *const u8, +/// )); +/// } /// ``` #[stable(feature = "ptr_eq", since = "1.17.0")] #[inline] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 4e79ea812044b..5ec21e6d92862 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -28,7 +28,7 @@ use crate::fmt; use crate::intrinsics::{assume, exact_div, unchecked_sub, is_aligned_and_not_null}; use crate::isize; use crate::iter::*; -use crate::ops::{FnMut, self}; +use crate::ops::{FnMut, Try, self}; use crate::option::Option; use crate::option::Option::{None, Some}; use crate::result::Result; @@ -63,7 +63,6 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) - #[allow(unused_attributes)] #[allow_internal_unstable(const_fn_union)] pub const fn len(&self) -> usize { unsafe { @@ -3181,6 +3180,39 @@ macro_rules! iterator { self.next_back() } + #[inline] + fn try_fold(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try + { + // manual unrolling is needed when there are conditional exits from the loop + let mut accum = init; + unsafe { + while len!(self) >= 4 { + accum = f(accum, next_unchecked!(self))?; + accum = f(accum, next_unchecked!(self))?; + accum = f(accum, next_unchecked!(self))?; + accum = f(accum, next_unchecked!(self))?; + } + while !is_empty!(self) { + accum = f(accum, next_unchecked!(self))?; + } + } + Try::from_ok(accum) + } + + #[inline] + fn fold(mut self, init: Acc, mut f: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + // Let LLVM unroll this, rather than using the default + // impl that would force the manual unrolling above + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x); + } + accum + } + #[inline] #[rustc_inherit_overflow_checks] fn position

) { + for lint in pass.get_lints() { + self.lints.push((lint, from_plugin)); let id = LintId::of(lint); if self.by_name.insert(lint.name_lower(), Id(id)).is_some() { - bug!("duplicate specification of lint {}", lint.name_lower()) + let msg = format!("duplicate specification of lint {}", lint.name_lower()); + match (sess, from_plugin) { + // We load builtin lints first, so a duplicate is a compiler bug. + // Use early_error when handling -W help with no crate. + (None, _) => early_error(config::ErrorOutputType::default(), &msg[..]), + (Some(_), false) => bug!("{}", msg), + + // A duplicate name from a plugin is a user error. + (Some(sess), true) => sess.err(&msg[..]), + } } + } + } - if let Some(FutureIncompatibleInfo { edition, .. }) = lint.future_incompatible { - if let Some(edition) = edition { - self.lint_groups.entry(edition.lint_name()) - .or_insert(LintGroup { - lint_ids: vec![], - from_plugin: lint.is_plugin, - depr: None, - }) - .lint_ids.push(id); - } + pub fn register_future_incompatible(&mut self, + sess: Option<&Session>, + lints: Vec) { - self.lint_groups.entry("future_incompatible") - .or_insert(LintGroup { - lint_ids: vec![], - from_plugin: lint.is_plugin, - depr: None, - }) - .lint_ids.push(id); + for edition in edition::ALL_EDITIONS { + let lints = lints.iter().filter(|f| f.edition == Some(*edition)).map(|f| f.id) + .collect::>(); + if !lints.is_empty() { + self.register_group(sess, false, edition.lint_name(), None, lints) } } + + let mut future_incompatible = Vec::with_capacity(lints.len()); + for lint in lints { + future_incompatible.push(lint.id); + self.future_incompatible.insert(lint.id, lint); + } + + self.register_group( + sess, + false, + "future_incompatible", + None, + future_incompatible, + ); + } + + pub fn future_incompatible(&self, id: LintId) -> Option<&FutureIncompatibleInfo> { + self.future_incompatible.get(&id) } pub fn register_group_alias( @@ -229,6 +277,7 @@ impl LintStore { pub fn register_group( &mut self, + sess: Option<&Session>, from_plugin: bool, name: &'static str, deprecated_name: Option<&'static str>, @@ -251,7 +300,16 @@ impl LintStore { } if !new { - bug!("duplicate specification of lint group {}", name); + let msg = format!("duplicate specification of lint group {}", name); + match (sess, from_plugin) { + // We load builtin lints first, so a duplicate is a compiler bug. + // Use early_error when handling -W help with no crate. + (None, _) => early_error(config::ErrorOutputType::default(), &msg[..]), + (Some(_), false) => bug!("{}", msg), + + // A duplicate name from a plugin is a user error. + (Some(sess), true) => sess.err(&msg[..]), + } } } @@ -464,7 +522,7 @@ pub struct LateContext<'a, 'tcx> { pub access_levels: &'a AccessLevels, /// The store of registered lints and the lint levels. - lint_store: &'tcx LintStore, + lint_store: ReadGuard<'a, LintStore>, last_node_with_lint_attrs: hir::HirId, @@ -492,7 +550,7 @@ pub struct EarlyContext<'a> { builder: LintLevelsBuilder<'a>, /// The store of registered lints and the lint levels. - lint_store: &'a LintStore, + lint_store: ReadGuard<'a, LintStore>, buffered: LintBuffer, } @@ -581,15 +639,14 @@ pub trait LintContext: Sized { impl<'a> EarlyContext<'a> { fn new( sess: &'a Session, - lint_store: &'a LintStore, krate: &'a ast::Crate, buffered: LintBuffer, ) -> EarlyContext<'a> { EarlyContext { sess, krate, - lint_store, - builder: LintLevelSets::builder(sess, lint_store), + lint_store: sess.lint_store.borrow(), + builder: LintLevelSets::builder(sess), buffered, } } @@ -624,7 +681,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { f: F) where F: FnOnce(&mut Self) { - let push = self.context.builder.push(attrs, &self.context.lint_store); + let push = self.context.builder.push(attrs); self.check_id(id); self.enter_attrs(attrs); f(self); @@ -818,7 +875,7 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { _ => {} } - path.push(disambiguated_data.data.as_symbol()); + path.push(disambiguated_data.data.as_interned_str().as_symbol()); Ok(path) } @@ -1298,6 +1355,10 @@ impl LintPass for LateLintPassObjects<'_> { fn name(&self) -> &'static str { panic!() } + + fn get_lints(&self) -> LintArray { + panic!() + } } macro_rules! expand_late_lint_pass_impl_methods { @@ -1332,7 +1393,7 @@ fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( tables: &ty::TypeckTables::empty(None), param_env: ty::ParamEnv::empty(), access_levels, - lint_store: &tcx.lint_store, + lint_store: tcx.sess.lint_store.borrow(), last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(), generics: None, only_module: true, @@ -1364,8 +1425,8 @@ pub fn late_lint_mod<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( late_lint_mod_pass(tcx, module_def_id, builtin_lints); - let mut passes: Vec<_> = tcx.lint_store.late_module_passes - .iter().map(|pass| (pass)()).collect(); + let mut passes: Vec<_> = tcx.sess.lint_store.borrow().late_module_passes + .iter().map(|pass| pass.fresh_late_pass()).collect(); if !passes.is_empty() { late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] }); @@ -1382,7 +1443,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc tables: &ty::TypeckTables::empty(None), param_env: ty::ParamEnv::empty(), access_levels, - lint_store: &tcx.lint_store, + lint_store: tcx.sess.lint_store.borrow(), last_node_with_lint_attrs: hir::CRATE_HIR_ID, generics: None, only_module: false, @@ -1406,8 +1467,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc } fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) { - let mut passes = tcx.lint_store - .late_passes.iter().map(|p| (p)()).collect::>(); + let mut passes = tcx.sess.lint_store.borrow().late_passes.lock().take().unwrap(); if !tcx.sess.opts.debugging_opts.no_interleave_lints { if !passes.is_empty() { @@ -1422,8 +1482,8 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, b }); } - let mut passes: Vec<_> = tcx.lint_store.late_module_passes - .iter().map(|pass| (pass)()).collect(); + let mut passes: Vec<_> = tcx.sess.lint_store.borrow().late_module_passes + .iter().map(|pass| pass.fresh_late_pass()).collect(); for pass in &mut passes { time(tcx.sess, &format!("running late module lint: {}", pass.name()), || { @@ -1431,6 +1491,9 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, b }); } } + + // Put the passes back in the session. + *tcx.sess.lint_store.borrow().late_passes.lock() = Some(passes); } /// Performs lint checking on a crate. @@ -1462,6 +1525,10 @@ impl LintPass for EarlyLintPassObjects<'_> { fn name(&self) -> &'static str { panic!() } + + fn get_lints(&self) -> LintArray { + panic!() + } } macro_rules! expand_early_lint_pass_impl_methods { @@ -1486,13 +1553,12 @@ early_lint_methods!(early_lint_pass_impl, []); fn early_lint_crate( sess: &Session, - lint_store: &LintStore, krate: &ast::Crate, pass: T, buffered: LintBuffer, ) -> LintBuffer { let mut cx = EarlyContextAndPass { - context: EarlyContext::new(sess, lint_store, krate, buffered), + context: EarlyContext::new(sess, krate, buffered), pass, }; @@ -1511,30 +1577,28 @@ fn early_lint_crate( pub fn check_ast_crate( sess: &Session, - lint_store: &LintStore, krate: &ast::Crate, pre_expansion: bool, builtin_lints: T, ) { - let (mut passes, mut buffered): (Vec<_>, _) = if pre_expansion { + let (mut passes, mut buffered) = if pre_expansion { ( - lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect(), + sess.lint_store.borrow_mut().pre_expansion_passes.take().unwrap(), LintBuffer::default(), ) } else { ( - lint_store.early_passes.iter().map(|p| (p)()).collect(), + sess.lint_store.borrow_mut().early_passes.take().unwrap(), sess.buffered_lints.borrow_mut().take().unwrap(), ) }; if !sess.opts.debugging_opts.no_interleave_lints { - buffered = early_lint_crate(sess, lint_store, krate, builtin_lints, buffered); + buffered = early_lint_crate(sess, krate, builtin_lints, buffered); if !passes.is_empty() { buffered = early_lint_crate( sess, - lint_store, krate, EarlyLintPassObjects { lints: &mut passes[..] }, buffered, @@ -1545,7 +1609,6 @@ pub fn check_ast_crate( buffered = time(sess, &format!("running lint: {}", pass.name()), || { early_lint_crate( sess, - lint_store, krate, EarlyLintPassObjects { lints: slice::from_mut(pass) }, buffered, @@ -1554,6 +1617,13 @@ pub fn check_ast_crate( } } + // Put the lint store levels and passes back in the session. + if pre_expansion { + sess.lint_store.borrow_mut().pre_expansion_passes = Some(passes); + } else { + sess.lint_store.borrow_mut().early_passes = Some(passes); + } + // All of the buffered lints should have been emitted at this point. // If not, that means that we somehow buffered a lint for a node id // that was not lint-checked (perhaps it doesn't exist?). This is a bug. @@ -1583,7 +1653,7 @@ impl Decodable for LintId { fn decode(d: &mut D) -> Result { let s = d.read_str()?; ty::tls::with(|tcx| { - match tcx.lint_store.find_lints(&s) { + match tcx.sess.lint_store.borrow().find_lints(&s) { Ok(ids) => { if ids.len() != 0 { panic!("invalid lint-id `{}`", s); diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 4c60492e470c2..16d19e41db4f4 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -3,16 +3,16 @@ use std::cmp; use crate::hir::HirId; use crate::ich::StableHashingContext; use crate::lint::builtin; -use crate::lint::context::{LintStore, CheckLintNameResult}; +use crate::lint::context::CheckLintNameResult; use crate::lint::{self, Lint, LintId, Level, LintSource}; use crate::session::Session; use crate::util::nodemap::FxHashMap; use errors::{Applicability, DiagnosticBuilder}; -use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, + StableHasher, StableHasherResult}; use syntax::ast; use syntax::attr; use syntax::feature_gate; -use syntax::print::pprust; use syntax::source_map::MultiSpan; use syntax::symbol::{Symbol, sym}; @@ -35,20 +35,21 @@ enum LintSet { } impl LintLevelSets { - pub fn new(sess: &Session, lint_store: &LintStore) -> LintLevelSets { + pub fn new(sess: &Session) -> LintLevelSets { let mut me = LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid, }; - me.process_command_line(sess, lint_store); + me.process_command_line(sess); return me } - pub fn builder<'a>(sess: &'a Session, store: &LintStore) -> LintLevelsBuilder<'a> { - LintLevelsBuilder::new(sess, LintLevelSets::new(sess, store)) + pub fn builder(sess: &Session) -> LintLevelsBuilder<'_> { + LintLevelsBuilder::new(sess, LintLevelSets::new(sess)) } - fn process_command_line(&mut self, sess: &Session, store: &LintStore) { + fn process_command_line(&mut self, sess: &Session) { + let store = sess.lint_store.borrow(); let mut specs = FxHashMap::default(); self.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid); @@ -185,8 +186,9 @@ impl<'a> LintLevelsBuilder<'a> { /// #[allow] /// /// Don't forget to call `pop`! - pub fn push(&mut self, attrs: &[ast::Attribute], store: &LintStore) -> BuilderPush { + pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush { let mut specs = FxHashMap::default(); + let store = self.sess.lint_store.borrow(); let sess = self.sess; let bad_attr = |span| { struct_span_err!(sess, span, E0452, "malformed lint attribute input") @@ -200,7 +202,11 @@ impl<'a> LintLevelsBuilder<'a> { let meta = unwrap_or!(attr.meta(), continue); attr::mark_used(attr); - let mut metas = unwrap_or!(meta.meta_item_list(), continue); + let mut metas = if let Some(metas) = meta.meta_item_list() { + metas + } else { + continue; + }; if metas.is_empty() { // FIXME (#55112): issue unused-attributes lint for `#[level()]` @@ -280,7 +286,7 @@ impl<'a> LintLevelsBuilder<'a> { tool_ident.span, E0710, "an unknown tool name found in scoped lint: `{}`", - pprust::path_to_string(&meta_item.path), + meta_item.path ); continue; } @@ -520,7 +526,9 @@ impl LintLevelMap { impl<'a> HashStable> for LintLevelMap { #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let LintLevelMap { ref sets, ref id_to_set, @@ -559,7 +567,9 @@ impl<'a> HashStable> for LintLevelMap { impl HashStable for LintId { #[inline] - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut HCX, + hasher: &mut StableHasher) { self.lint_name_raw().hash_stable(hcx, hasher); } } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 3c35bdae66e9d..5b490b701267d 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -28,7 +28,6 @@ use crate::hir::intravisit; use crate::hir; use crate::lint::builtin::BuiltinLintDiagnostics; use crate::lint::builtin::parser::{ILL_FORMED_ATTRIBUTE_INPUT, META_VARIABLE_MISUSE}; -use crate::lint::builtin::parser::INCOMPLETE_INCLUDE; use crate::session::{Session, DiagnosticMessageId}; use crate::ty::TyCtxt; use crate::ty::query::Providers; @@ -39,13 +38,13 @@ use syntax::ast; use syntax::source_map::{MultiSpan, ExpnKind, DesugaringKind}; use syntax::early_buffered_lints::BufferedEarlyLintId; use syntax::edition::Edition; -use syntax_expand::base::MacroKind; +use syntax::ext::base::MacroKind; use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; pub use crate::lint::context::{LateContext, EarlyContext, LintContext, LintStore, check_crate, check_ast_crate, late_lint_mod, CheckLintNameResult, - BufferedEarlyLint,}; + FutureIncompatibleInfo, BufferedEarlyLint,}; /// Specification of a single lint. #[derive(Copy, Clone, Debug)] @@ -76,41 +75,14 @@ pub struct Lint { /// `true` if this lint is reported even inside expansions of external macros. pub report_in_external_macro: bool, - - pub future_incompatible: Option, - - pub is_plugin: bool, -} - -/// Extra information for a future incompatibility lint. -#[derive(Copy, Clone, Debug)] -pub struct FutureIncompatibleInfo { - /// e.g., a URL for an issue/PR/RFC or error code - pub reference: &'static str, - /// If this is an edition fixing lint, the edition in which - /// this lint becomes obsolete - pub edition: Option, } impl Lint { - pub const fn default_fields_for_macro() -> Self { - Lint { - name: "", - default_level: Level::Forbid, - desc: "", - edition_lint_opts: None, - is_plugin: false, - report_in_external_macro: false, - future_incompatible: None, - } - } - /// Returns the `rust::lint::Lint` for a `syntax::early_buffered_lints::BufferedEarlyLintId`. pub fn from_parser_lint_id(lint_id: BufferedEarlyLintId) -> &'static Self { match lint_id { BufferedEarlyLintId::IllFormedAttributeInput => ILL_FORMED_ATTRIBUTE_INPUT, BufferedEarlyLintId::MetaVariableMisuse => META_VARIABLE_MISUSE, - BufferedEarlyLintId::IncompleteInclude => INCOMPLETE_INCLUDE, } } @@ -131,21 +103,18 @@ impl Lint { #[macro_export] macro_rules! declare_lint { ($vis: vis $NAME: ident, $Level: ident, $desc: expr) => ( - declare_lint!( - $vis $NAME, $Level, $desc, - ); + declare_lint!{$vis $NAME, $Level, $desc, false} ); - ($vis: vis $NAME: ident, $Level: ident, $desc: expr, - $(@future_incompatible = $fi:expr;)? $($v:ident),*) => ( + ($vis: vis $NAME: ident, $Level: ident, $desc: expr, report_in_external_macro: $rep: expr) => ( + declare_lint!{$vis $NAME, $Level, $desc, $rep} + ); + ($vis: vis $NAME: ident, $Level: ident, $desc: expr, $external: expr) => ( $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint { name: stringify!($NAME), default_level: $crate::lint::$Level, desc: $desc, edition_lint_opts: None, - is_plugin: false, - $($v: true,)* - $(future_incompatible: Some($fi),)* - ..$crate::lint::Lint::default_fields_for_macro() + report_in_external_macro: $external, }; ); ($vis: vis $NAME: ident, $Level: ident, $desc: expr, @@ -157,7 +126,6 @@ macro_rules! declare_lint { desc: $desc, edition_lint_opts: Some(($lint_edition, $crate::lint::Level::$edition_level)), report_in_external_macro: false, - is_plugin: false, }; ); } @@ -186,8 +154,6 @@ macro_rules! declare_tool_lint { desc: $desc, edition_lint_opts: None, report_in_external_macro: $external, - future_incompatible: None, - is_plugin: true, }; ); } @@ -205,6 +171,14 @@ pub type LintArray = Vec<&'static Lint>; pub trait LintPass { fn name(&self) -> &'static str; + + /// Gets descriptions of the lints this `LintPass` object can emit. + /// + /// N.B., there is no enforcement that the object only emits lints it registered. + /// And some `rustc` internal `LintPass`es register lints to be emitted by other + /// parts of the compiler. If you want enforced access restrictions for your + /// `Lint`, make it a private `static` item in its own module. + fn get_lints(&self) -> LintArray; } /// Implements `LintPass for $name` with the given list of `Lint` statics. @@ -213,9 +187,7 @@ macro_rules! impl_lint_pass { ($name:ident => [$($lint:expr),* $(,)?]) => { impl LintPass for $name { fn name(&self) -> &'static str { stringify!($name) } - } - impl $name { - pub fn get_lints() -> LintArray { $crate::lint_array!($($lint),*) } + fn get_lints(&self) -> LintArray { $crate::lint_array!($($lint),*) } } }; } @@ -313,6 +285,9 @@ macro_rules! expand_lint_pass_methods { macro_rules! declare_late_lint_pass { ([], [$hir:tt], [$($methods:tt)*]) => ( pub trait LateLintPass<'a, $hir>: LintPass { + fn fresh_late_pass(&self) -> LateLintPassObject { + panic!() + } expand_lint_pass_methods!(&LateContext<'a, $hir>, [$($methods)*]); } ) @@ -350,12 +325,6 @@ macro_rules! declare_combined_late_lint_pass { $($passes: $constructor,)* } } - - $v fn get_lints() -> LintArray { - let mut lints = Vec::new(); - $(lints.extend_from_slice(&$passes::get_lints());)* - lints - } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $name { @@ -366,6 +335,12 @@ macro_rules! declare_combined_late_lint_pass { fn name(&self) -> &'static str { panic!() } + + fn get_lints(&self) -> LintArray { + let mut lints = Vec::new(); + $(lints.extend_from_slice(&self.$passes.get_lints());)* + lints + } } ) } @@ -477,12 +452,6 @@ macro_rules! declare_combined_early_lint_pass { $($passes: $constructor,)* } } - - $v fn get_lints() -> LintArray { - let mut lints = Vec::new(); - $(lints.extend_from_slice(&$passes::get_lints());)* - lints - } } impl EarlyLintPass for $name { @@ -493,6 +462,12 @@ macro_rules! declare_combined_early_lint_pass { fn name(&self) -> &'static str { panic!() } + + fn get_lints(&self) -> LintArray { + let mut lints = Vec::new(); + $(lints.extend_from_slice(&self.$passes.get_lints());)* + lints + } } ) } @@ -672,8 +647,9 @@ pub fn struct_lint_level<'a>(sess: &'a Session, }; // 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 = lint.future_incompatible; + 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 @@ -777,15 +753,13 @@ pub fn maybe_lint_level_root(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap { assert_eq!(cnum, LOCAL_CRATE); - let store = &tcx.lint_store; let mut builder = LintLevelMapBuilder { - levels: LintLevelSets::builder(tcx.sess, &store), + levels: LintLevelSets::builder(tcx.sess), tcx: tcx, - store: store, }; let krate = tcx.hir().krate(); - let push = builder.levels.push(&krate.attrs, &store); + let push = builder.levels.push(&krate.attrs); builder.levels.register_id(hir::CRATE_HIR_ID); for macro_def in &krate.exported_macros { builder.levels.register_id(macro_def.hir_id); @@ -796,20 +770,19 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap { tcx.arena.alloc(builder.levels.build_map()) } -struct LintLevelMapBuilder<'a, 'tcx> { +struct LintLevelMapBuilder<'tcx> { levels: levels::LintLevelsBuilder<'tcx>, tcx: TyCtxt<'tcx>, - store: &'a LintStore, } -impl LintLevelMapBuilder<'_, '_> { +impl LintLevelMapBuilder<'tcx> { fn with_lint_attrs(&mut self, id: hir::HirId, attrs: &[ast::Attribute], f: F) where F: FnOnce(&mut Self) { - let push = self.levels.push(attrs, self.store); + let push = self.levels.push(attrs); if push.changed { self.levels.register_id(id); } @@ -818,7 +791,7 @@ impl LintLevelMapBuilder<'_, '_> { } } -impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> { +impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> { fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> { intravisit::NestedVisitorMap::All(&self.tcx.hir()) } diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs index 256a08d7e90c3..09fa924efc7ab 100644 --- a/src/librustc/macros.rs +++ b/src/librustc/macros.rs @@ -97,9 +97,9 @@ macro_rules! impl_stable_hash_for { where $($T: ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>>),* { #[inline] - fn hash_stable(&self, - __ctx: &mut $crate::ich::StableHashingContext<'a>, - __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { + fn hash_stable(&self, + __ctx: &mut $crate::ich::StableHashingContext<'a>, + __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { use $enum_path::*; ::std::mem::discriminant(self).hash_stable(__ctx, __hasher); @@ -128,9 +128,9 @@ macro_rules! impl_stable_hash_for { where $($T: ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>>),* { #[inline] - fn hash_stable(&self, - __ctx: &mut $crate::ich::StableHashingContext<'a>, - __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { + fn hash_stable(&self, + __ctx: &mut $crate::ich::StableHashingContext<'a>, + __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { let $struct_name { $(ref $field),* } = *self; @@ -153,9 +153,9 @@ macro_rules! impl_stable_hash_for { where $($T: ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>>),* { #[inline] - fn hash_stable(&self, - __ctx: &mut $crate::ich::StableHashingContext<'a>, - __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { + fn hash_stable(&self, + __ctx: &mut $crate::ich::StableHashingContext<'a>, + __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { let $struct_name ( $(ref $field),* ) = *self; @@ -173,9 +173,9 @@ macro_rules! impl_stable_hash_for_spanned { impl HashStable> for ::syntax::source_map::Spanned<$T> { #[inline] - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { self.node.hash_stable(hcx, hasher); self.span.hash_stable(hcx, hasher); } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index d5558db2397e7..ddf6262b7382e 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -16,7 +16,7 @@ use syntax::ast; use syntax::symbol::Symbol; use syntax_pos::Span; use rustc_target::spec::Target; -use rustc_data_structures::sync::{self, MetadataRef}; +use rustc_data_structures::sync::{self, MetadataRef, Lrc}; use rustc_macros::HashStable; pub use self::NativeLibraryKind::*; @@ -32,12 +32,6 @@ pub struct CrateSource { pub rmeta: Option<(PathBuf, PathKind)>, } -impl CrateSource { - pub fn paths(&self) -> impl Iterator { - self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).map(|p| &p.0) - } -} - #[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, HashStable)] pub enum DepKind { @@ -102,8 +96,6 @@ pub enum NativeLibraryKind { NativeStaticNobundle, /// macOS-specific NativeFramework, - /// Windows dynamic library without import library. - NativeRawDylib, /// default way to specify a dynamic library NativeUnknown, } @@ -117,7 +109,7 @@ pub struct NativeLibrary { pub wasm_import_module: Option, } -#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct ForeignModule { pub foreign_items: Vec, pub def_id: DefId, @@ -156,7 +148,9 @@ pub enum ExternCrateSource { /// such ids DefId, ), - /// Crate is implicitly loaded by a path resolving through extern prelude. + // Crate is loaded by `use`. + Use, + /// Crate is implicitly loaded by an absolute path. Path, } @@ -191,8 +185,6 @@ pub trait MetadataLoader { -> Result; } -pub type MetadataLoaderDyn = dyn MetadataLoader + Sync; - /// A store of Rust crates, through which their metadata can be accessed. /// /// Note that this trait should probably not be expanding today. All new @@ -203,19 +195,20 @@ pub type MetadataLoaderDyn = dyn MetadataLoader + Sync; /// (it'd break incremental compilation) and should only be called pre-HIR (e.g. /// during resolve) pub trait CrateStore { - fn crate_data_as_any(&self, cnum: CrateNum) -> &dyn Any; + fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc; // resolve fn def_key(&self, def: DefId) -> DefKey; fn def_path(&self, def: DefId) -> hir_map::DefPath; fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash; - fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable; + fn def_path_table(&self, cnum: CrateNum) -> Lrc; // "queries" used in resolve that aren't tracked for incremental compilation fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool; fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator; fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh; + fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option; fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics; fn postorder_cnums_untracked(&self) -> Vec; diff --git a/src/librustc_passes/dead.rs b/src/librustc/middle/dead.rs similarity index 98% rename from src/librustc_passes/dead.rs rename to src/librustc/middle/dead.rs index f2aef2c12c7df..7c75a1447e26d 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc/middle/dead.rs @@ -2,18 +2,18 @@ // closely. The idea is that all reachable symbols are live, codes called // from live codes are live, and everything else is dead. -use rustc::hir::Node; -use rustc::hir::{self, PatKind, TyKind}; -use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use rustc::hir::itemlikevisit::ItemLikeVisitor; - -use rustc::hir::def::{CtorOf, Res, DefKind}; -use rustc::hir::CodegenFnAttrFlags; -use rustc::hir::def_id::{DefId, LOCAL_CRATE}; -use rustc::lint; -use rustc::middle::privacy; -use rustc::ty::{self, DefIdTree, TyCtxt}; -use rustc::util::nodemap::FxHashSet; +use crate::hir::Node; +use crate::hir::{self, PatKind, TyKind}; +use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use crate::hir::itemlikevisit::ItemLikeVisitor; + +use crate::hir::def::{CtorOf, Res, DefKind}; +use crate::hir::CodegenFnAttrFlags; +use crate::hir::def_id::{DefId, LOCAL_CRATE}; +use crate::lint; +use crate::middle::privacy; +use crate::ty::{self, DefIdTree, TyCtxt}; +use crate::util::nodemap::FxHashSet; use rustc_data_structures::fx::FxHashMap; diff --git a/src/librustc_passes/entry.rs b/src/librustc/middle/entry.rs similarity index 95% rename from src/librustc_passes/entry.rs rename to src/librustc/middle/entry.rs index bf68807a0c29b..660fe14ba0700 100644 --- a/src/librustc_passes/entry.rs +++ b/src/librustc/middle/entry.rs @@ -1,15 +1,15 @@ -use rustc::hir::map as hir_map; -use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; -use rustc::session::{config, Session}; -use rustc::session::config::EntryFnType; +use crate::hir::map as hir_map; +use crate::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; +use crate::session::{config, Session}; +use crate::session::config::EntryFnType; use syntax::attr; use syntax::entry::EntryPointType; use syntax::symbol::sym; use syntax_pos::Span; -use rustc::hir::{HirId, Item, ItemKind, ImplItem, TraitItem}; -use rustc::hir::itemlikevisit::ItemLikeVisitor; -use rustc::ty::TyCtxt; -use rustc::ty::query::Providers; +use crate::hir::{HirId, Item, ItemKind, ImplItem, TraitItem}; +use crate::hir::itemlikevisit::ItemLikeVisitor; +use crate::ty::TyCtxt; +use crate::ty::query::Providers; struct EntryContext<'a, 'tcx> { session: &'a Session, diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs index 4d14299751c3d..202788093046a 100644 --- a/src/librustc/middle/exported_symbols.rs +++ b/src/librustc/middle/exported_symbols.rs @@ -1,6 +1,7 @@ use crate::hir::def_id::{DefId, LOCAL_CRATE}; use crate::ich::StableHashingContext; -use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; +use rustc_data_structures::stable_hasher::{StableHasher, HashStable, + StableHasherResult}; use std::cmp; use std::mem; use crate::ty::{self, TyCtxt}; @@ -93,7 +94,9 @@ pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String { } impl<'a, 'tcx> HashStable> for ExportedSymbol<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { ExportedSymbol::NonGeneric(def_id) => { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index bb7ac5d8dbe1a..45b660f5c67f6 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -2,20 +2,25 @@ //! normal visitor, which just walks the entire body in one shot, the //! `ExprUseVisitor` determines how expressions are being used. +pub use self::LoanCause::*; pub use self::ConsumeMode::*; +pub use self::MoveReason::*; +pub use self::MatchMode::*; +use self::TrackMatchMode::*; use self::OverloadedCallType::*; -use crate::hir::def::Res; +use crate::hir::def::{CtorOf, Res, DefKind}; use crate::hir::def_id::DefId; use crate::hir::ptr::P; use crate::infer::InferCtxt; use crate::middle::mem_categorization as mc; use crate::middle::region; -use crate::ty::{self, TyCtxt, adjustment}; +use crate::ty::{self, DefIdTree, TyCtxt, adjustment}; use crate::hir::{self, PatKind}; use std::rc::Rc; use syntax_pos::Span; +use crate::util::nodemap::ItemLocalSet; /////////////////////////////////////////////////////////////////////////// // The Delegate trait @@ -25,19 +30,161 @@ use syntax_pos::Span; pub trait Delegate<'tcx> { // The value found at `cmt` is either copied or moved, depending // on mode. - fn consume(&mut self, cmt: &mc::cmt_<'tcx>, mode: ConsumeMode); - - // The value found at `cmt` is being borrowed with kind `bk`. - fn borrow(&mut self, cmt: &mc::cmt_<'tcx>, bk: ty::BorrowKind); + fn consume(&mut self, + consume_id: hir::HirId, + consume_span: Span, + cmt: &mc::cmt_<'tcx>, + mode: ConsumeMode); + + // The value found at `cmt` has been determined to match the + // pattern binding `matched_pat`, and its subparts are being + // copied or moved depending on `mode`. Note that `matched_pat` + // is called on all variant/structs in the pattern (i.e., the + // interior nodes of the pattern's tree structure) while + // consume_pat is called on the binding identifiers in the pattern + // (which are leaves of the pattern's tree structure). + // + // Note that variants/structs and identifiers are disjoint; thus + // `matched_pat` and `consume_pat` are never both called on the + // same input pattern structure (though of `consume_pat` can be + // called on a subpart of an input passed to `matched_pat). + fn matched_pat(&mut self, + matched_pat: &hir::Pat, + cmt: &mc::cmt_<'tcx>, + mode: MatchMode); + + // The value found at `cmt` is either copied or moved via the + // pattern binding `consume_pat`, depending on mode. + fn consume_pat(&mut self, + consume_pat: &hir::Pat, + cmt: &mc::cmt_<'tcx>, + mode: ConsumeMode); + + // The value found at `borrow` is being borrowed at the point + // `borrow_id` for the region `loan_region` with kind `bk`. + fn borrow(&mut self, + borrow_id: hir::HirId, + borrow_span: Span, + cmt: &mc::cmt_<'tcx>, + loan_region: ty::Region<'tcx>, + bk: ty::BorrowKind, + loan_cause: LoanCause); + + // The local variable `id` is declared but not initialized. + fn decl_without_init(&mut self, + id: hir::HirId, + span: Span); // The path at `cmt` is being assigned to. - fn mutate(&mut self, assignee_cmt: &mc::cmt_<'tcx>); + fn mutate(&mut self, + assignment_id: hir::HirId, + assignment_span: Span, + assignee_cmt: &mc::cmt_<'tcx>, + mode: MutateMode); + + // A nested closure or generator - only one layer deep. + fn nested_body(&mut self, _body_id: hir::BodyId) {} +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum LoanCause { + ClosureCapture(Span), + AddrOf, + AutoRef, + AutoUnsafe, + RefBinding, + OverloadedOperator, + ClosureInvocation, + ForLoop, + MatchDiscriminant } #[derive(Copy, Clone, PartialEq, Debug)] pub enum ConsumeMode { Copy, // reference to x where x has a type that copies - Move, // reference to x where x has a type that moves + Move(MoveReason), // reference to x where x has a type that moves +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum MoveReason { + DirectRefMove, + PatBindingMove, + CaptureMove, +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum MatchMode { + NonBindingMatch, + BorrowingMatch, + CopyingMatch, + MovingMatch, +} + +#[derive(Copy, Clone, PartialEq, Debug)] +enum TrackMatchMode { + Unknown, + Definite(MatchMode), + Conflicting, +} + +impl TrackMatchMode { + // Builds up the whole match mode for a pattern from its constituent + // parts. The lattice looks like this: + // + // Conflicting + // / \ + // / \ + // Borrowing Moving + // \ / + // \ / + // Copying + // | + // NonBinding + // | + // Unknown + // + // examples: + // + // * `(_, some_int)` pattern is Copying, since + // NonBinding + Copying => Copying + // + // * `(some_int, some_box)` pattern is Moving, since + // Copying + Moving => Moving + // + // * `(ref x, some_box)` pattern is Conflicting, since + // Borrowing + Moving => Conflicting + // + // Note that the `Unknown` and `Conflicting` states are + // represented separately from the other more interesting + // `Definite` states, which simplifies logic here somewhat. + fn lub(&mut self, mode: MatchMode) { + *self = match (*self, mode) { + // Note that clause order below is very significant. + (Unknown, new) => Definite(new), + (Definite(old), new) if old == new => Definite(old), + + (Definite(old), NonBindingMatch) => Definite(old), + (Definite(NonBindingMatch), new) => Definite(new), + + (Definite(old), CopyingMatch) => Definite(old), + (Definite(CopyingMatch), new) => Definite(new), + + (Definite(_), _) => Conflicting, + (Conflicting, _) => *self, + }; + } + + fn match_mode(&self) -> MatchMode { + match *self { + Unknown => NonBindingMatch, + Definite(mode) => mode, + Conflicting => { + // Conservatively return MovingMatch to let the + // compiler continue to make progress. + MovingMatch + } + } + } } #[derive(Copy, Clone, PartialEq, Debug)] @@ -114,6 +261,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// - `param_env` --- parameter environment for trait lookups (esp. pertaining to `Copy`) /// - `region_scope_tree` --- region scope tree for the code being analyzed /// - `tables` --- typeck results for the code being analyzed + /// - `rvalue_promotable_map` --- if you care about rvalue promotion, then provide + /// the map here (it can be computed with `tcx.rvalue_promotable_map(def_id)`). + /// `None` means that rvalues will be given more conservative lifetimes. /// /// See also `with_infer`, which is used *during* typeck. pub fn new( @@ -123,13 +273,15 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, region_scope_tree: &'a region::ScopeTree, tables: &'a ty::TypeckTables<'tcx>, + rvalue_promotable_map: Option<&'tcx ItemLocalSet>, ) -> Self { ExprUseVisitor { mc: mc::MemCategorizationContext::new(tcx, param_env, body_owner, region_scope_tree, - tables), + tables, + rvalue_promotable_map), delegate, param_env, } @@ -165,9 +317,16 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { 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( + region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::Node + })); 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(param_cmt, ¶m.pat); @@ -180,11 +339,15 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.mc.tcx } - fn delegate_consume(&mut self, cmt: &mc::cmt_<'tcx>) { - debug!("delegate_consume(cmt={:?})", cmt); + fn delegate_consume(&mut self, + consume_id: hir::HirId, + consume_span: Span, + cmt: &mc::cmt_<'tcx>) { + debug!("delegate_consume(consume_id={}, cmt={:?})", + consume_id, cmt); - let mode = copy_or_move(&self.mc, self.param_env, cmt); - self.delegate.consume(cmt, mode); + let mode = copy_or_move(&self.mc, self.param_env, cmt, DirectRefMove); + self.delegate.consume(consume_id, consume_span, cmt, mode); } fn consume_exprs(&mut self, exprs: &[hir::Expr]) { @@ -197,21 +360,30 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { debug!("consume_expr(expr={:?})", expr); let cmt = return_if_err!(self.mc.cat_expr(expr)); - self.delegate_consume(&cmt); + self.delegate_consume(expr.hir_id, expr.span, &cmt); self.walk_expr(expr); } - fn mutate_expr(&mut self, expr: &hir::Expr) { + fn mutate_expr(&mut self, + span: Span, + assignment_expr: &hir::Expr, + expr: &hir::Expr, + mode: MutateMode) { let cmt = return_if_err!(self.mc.cat_expr(expr)); - self.delegate.mutate(&cmt); + self.delegate.mutate(assignment_expr.hir_id, span, &cmt, mode); self.walk_expr(expr); } - fn borrow_expr(&mut self, expr: &hir::Expr, bk: ty::BorrowKind) { - debug!("borrow_expr(expr={:?}, bk={:?})", expr, bk); + fn borrow_expr(&mut self, + expr: &hir::Expr, + r: ty::Region<'tcx>, + bk: ty::BorrowKind, + cause: LoanCause) { + debug!("borrow_expr(expr={:?}, r={:?}, bk={:?})", + expr, r, bk); let cmt = return_if_err!(self.mc.cat_expr(expr)); - self.delegate.borrow(&cmt, bk); + self.delegate.borrow(expr.hir_id, expr.span, &cmt, r, bk, cause); self.walk_expr(expr) } @@ -229,24 +401,24 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { hir::ExprKind::Path(_) => { } hir::ExprKind::Type(ref subexpr, _) => { - self.walk_expr(subexpr) + self.walk_expr(&subexpr) } hir::ExprKind::Unary(hir::UnDeref, ref base) => { // *base - self.select_from_expr(base); + self.select_from_expr(&base); } hir::ExprKind::Field(ref base, _) => { // base.f - self.select_from_expr(base); + self.select_from_expr(&base); } hir::ExprKind::Index(ref lhs, ref rhs) => { // lhs[rhs] - self.select_from_expr(lhs); - self.consume_expr(rhs); + self.select_from_expr(&lhs); + self.consume_expr(&rhs); } hir::ExprKind::Call(ref callee, ref args) => { // callee(args) - self.walk_callee(expr, callee); + self.walk_callee(expr, &callee); self.consume_exprs(args); } @@ -264,11 +436,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { hir::ExprKind::Match(ref discr, ref arms, _) => { let discr_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&discr))); - self.borrow_expr(&discr, ty::ImmBorrow); + let r = self.tcx().lifetimes.re_empty; + self.borrow_expr(&discr, r, ty::ImmBorrow, MatchDiscriminant); // treatment of the discriminant is handled while walking the arms. for arm in arms { - self.walk_arm(discr_cmt.clone(), arm); + let mode = self.arm_move_mode(discr_cmt.clone(), arm); + let mode = mode.match_mode(); + self.walk_arm(discr_cmt.clone(), arm, mode); } } @@ -279,8 +454,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { hir::ExprKind::AddrOf(m, ref base) => { // &base // make sure that the thing we are pointing out stays valid // for the lifetime `scope_r` of the resulting ptr: - let bk = ty::BorrowKind::from_mutbl(m); - self.borrow_expr(&base, bk); + let expr_ty = return_if_err!(self.mc.expr_ty(expr)); + if let ty::Ref(r, _, _) = expr_ty.kind { + let bk = ty::BorrowKind::from_mutbl(m); + self.borrow_expr(&base, r, bk, AddrOf); + } } hir::ExprKind::InlineAsm(ref ia, ref outputs, ref inputs) => { @@ -288,7 +466,16 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { if o.is_indirect { self.consume_expr(output); } else { - self.mutate_expr(output); + self.mutate_expr( + output.span, + expr, + output, + if o.is_rw { + MutateMode::WriteAndRead + } else { + MutateMode::JustWrite + }, + ); } } self.consume_exprs(inputs); @@ -299,64 +486,65 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { hir::ExprKind::Err => {} hir::ExprKind::Loop(ref blk, _, _) => { - self.walk_block(blk); + self.walk_block(&blk); } hir::ExprKind::Unary(_, ref lhs) => { - self.consume_expr(lhs); + self.consume_expr(&lhs); } hir::ExprKind::Binary(_, ref lhs, ref rhs) => { - self.consume_expr(lhs); - self.consume_expr(rhs); + self.consume_expr(&lhs); + self.consume_expr(&rhs); } hir::ExprKind::Block(ref blk, _) => { - self.walk_block(blk); + self.walk_block(&blk); } hir::ExprKind::Break(_, ref opt_expr) | hir::ExprKind::Ret(ref opt_expr) => { if let Some(ref expr) = *opt_expr { - self.consume_expr(expr); + self.consume_expr(&expr); } } hir::ExprKind::Assign(ref lhs, ref rhs) => { - self.mutate_expr(lhs); - self.consume_expr(rhs); + self.mutate_expr(expr.span, expr, &lhs, MutateMode::JustWrite); + self.consume_expr(&rhs); } hir::ExprKind::Cast(ref base, _) => { - self.consume_expr(base); + self.consume_expr(&base); } hir::ExprKind::DropTemps(ref expr) => { - self.consume_expr(expr); + self.consume_expr(&expr); } hir::ExprKind::AssignOp(_, ref lhs, ref rhs) => { if self.mc.tables.is_method_call(expr) { self.consume_expr(lhs); } else { - self.mutate_expr(lhs); + self.mutate_expr(expr.span, expr, &lhs, MutateMode::WriteAndRead); } - self.consume_expr(rhs); + self.consume_expr(&rhs); } hir::ExprKind::Repeat(ref base, _) => { - self.consume_expr(base); + self.consume_expr(&base); } - hir::ExprKind::Closure(_, _, _, fn_decl_span, _) => { + hir::ExprKind::Closure(_, _, body_id, fn_decl_span, _) => { + self.delegate.nested_body(body_id); self.walk_captures(expr, fn_decl_span); } hir::ExprKind::Box(ref base) => { - self.consume_expr(base); + self.consume_expr(&base); } hir::ExprKind::Yield(ref value, _) => { - self.consume_expr(value); + self.consume_expr(&value); } } } @@ -372,12 +560,24 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { ty::Error => { } _ => { if let Some(def_id) = self.mc.tables.type_dependent_def_id(call.hir_id) { + let call_scope = region::Scope { + id: call.hir_id.local_id, + data: region::ScopeData::Node + }; match OverloadedCallType::from_method_id(self.tcx(), def_id) { FnMutOverloadedCall => { - self.borrow_expr(callee, ty::MutBorrow); + let call_scope_r = self.tcx().mk_region(ty::ReScope(call_scope)); + self.borrow_expr(callee, + call_scope_r, + ty::MutBorrow, + ClosureInvocation); } FnOverloadedCall => { - self.borrow_expr(callee, ty::ImmBorrow); + let call_scope_r = self.tcx().mk_region(ty::ReScope(call_scope)); + self.borrow_expr(callee, + call_scope_r, + ty::ImmBorrow, + ClosureInvocation); } FnOnceOverloadedCall => self.consume_expr(callee), } @@ -408,14 +608,22 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } fn walk_local(&mut self, local: &hir::Local) { - if let Some(ref expr) = local.init { - // Variable declarations with - // initializers are considered - // "assigns", which is handled by - // `walk_pat`: - self.walk_expr(&expr); - let init_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&expr))); - self.walk_irrefutable_pat(init_cmt, &local.pat); + match local.init { + None => { + local.pat.each_binding(|_, hir_id, span, _| { + self.delegate.decl_without_init(hir_id, span); + }) + } + + Some(ref expr) => { + // Variable declarations with + // initializers are considered + // "assigns", which is handled by + // `walk_pat`: + self.walk_expr(&expr); + let init_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&expr))); + self.walk_irrefutable_pat(init_cmt, &local.pat); + } } } @@ -465,7 +673,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { with_field.ident, with_field.ty(self.tcx(), substs) ); - self.delegate_consume(&cmt_field); + self.delegate_consume(with_expr.hir_id, with_expr.span, &cmt_field); } } } @@ -500,7 +708,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { adjustment::Adjust::Pointer(_) => { // Creating a closure/fn-pointer or unsizing consumes // the input and stores it into the resulting rvalue. - self.delegate_consume(&cmt); + self.delegate_consume(expr.hir_id, expr.span, &cmt); } adjustment::Adjust::Deref(None) => {} @@ -512,7 +720,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // this is an autoref of `x`. adjustment::Adjust::Deref(Some(ref deref)) => { let bk = ty::BorrowKind::from_mutbl(deref.mutbl); - self.delegate.borrow(&cmt, bk); + self.delegate.borrow(expr.hir_id, expr.span, &cmt, deref.region, bk, AutoRef); } adjustment::Adjust::Borrow(ref autoref) => { @@ -536,8 +744,13 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { autoref); match *autoref { - adjustment::AutoBorrow::Ref(_, m) => { - self.delegate.borrow(cmt_base, ty::BorrowKind::from_mutbl(m.into())); + adjustment::AutoBorrow::Ref(r, m) => { + self.delegate.borrow(expr.hir_id, + expr.span, + cmt_base, + r, + ty::BorrowKind::from_mutbl(m.into()), + AutoRef); } adjustment::AutoBorrow::RawPtr(m) => { @@ -545,14 +758,33 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { expr.hir_id, cmt_base); - - self.delegate.borrow(cmt_base, ty::BorrowKind::from_mutbl(m)); + // Converting from a &T to *T (or &mut T to *mut T) is + // treated as borrowing it for the enclosing temporary + // scope. + let r = self.tcx().mk_region(ty::ReScope( + region::Scope { + id: expr.hir_id.local_id, + data: region::ScopeData::Node + })); + + self.delegate.borrow(expr.hir_id, + expr.span, + cmt_base, + r, + ty::BorrowKind::from_mutbl(m), + AutoUnsafe); } } } - fn walk_arm(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm) { - self.walk_pat(discr_cmt.clone(), &arm.pat); + fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm) -> TrackMatchMode { + let mut mode = Unknown; + self.determine_pat_move_mode(discr_cmt.clone(), &arm.pat, &mut mode); + mode + } + + fn walk_arm(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm, mode: MatchMode) { + self.walk_pat(discr_cmt.clone(), &arm.pat, mode); if let Some(hir::Guard::If(ref e)) = arm.guard { self.consume_expr(e) @@ -564,12 +796,44 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// Walks a pat that occurs in isolation (i.e., top-level of fn argument or /// let binding, and *not* a match arm or nested pat.) fn walk_irrefutable_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat) { - self.walk_pat(cmt_discr, pat); + let mut mode = Unknown; + self.determine_pat_move_mode(cmt_discr.clone(), pat, &mut mode); + let mode = mode.match_mode(); + self.walk_pat(cmt_discr, pat, mode); } + /// Identifies any bindings within `pat` and accumulates within + /// `mode` whether the overall pattern/match structure is a move, + /// copy, or borrow. + fn determine_pat_move_mode(&mut self, + cmt_discr: mc::cmt<'tcx>, + pat: &hir::Pat, + mode: &mut TrackMatchMode) { + debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr, pat); + + return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| { + if let PatKind::Binding(..) = pat.kind { + let bm = *self.mc.tables.pat_binding_modes() + .get(pat.hir_id) + .expect("missing binding mode"); + match bm { + ty::BindByReference(..) => + mode.lub(BorrowingMatch), + ty::BindByValue(..) => { + match copy_or_move(&self.mc, self.param_env, &cmt_pat, PatBindingMove) { + Copy => mode.lub(CopyingMatch), + Move(..) => mode.lub(MovingMatch), + } + } + } + } + })); + } - /// The core driver for walking a pattern - fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat) { + /// The core driver for walking a pattern; `match_mode` must be + /// established up front, e.g., via `determine_pat_move_mode` (see + /// also `walk_irrefutable_pat` for patterns that stand alone). + fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) { debug!("walk_pat(cmt_discr={:?}, pat={:?})", cmt_discr, pat); let tcx = self.tcx(); @@ -577,9 +841,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { if let PatKind::Binding(_, canonical_id, ..) = pat.kind { debug!( - "walk_pat: binding cmt_pat={:?} pat={:?}", + "walk_pat: binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, + match_mode, ); if let Some(&bm) = mc.tables.pat_binding_modes().get(pat.hir_id) { debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); @@ -592,19 +857,21 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // binding being produced. let def = Res::Local(canonical_id); if let Ok(ref binding_cmt) = mc.cat_res(pat.hir_id, pat.span, pat_ty, def) { - delegate.mutate(binding_cmt); + delegate.mutate(pat.hir_id, pat.span, binding_cmt, MutateMode::Init); } // It is also a borrow or copy/move of the value being matched. match bm { ty::BindByReference(m) => { - let bk = ty::BorrowKind::from_mutbl(m); - delegate.borrow(&cmt_pat, bk); + if let ty::Ref(r, _, _) = pat_ty.kind { + let bk = ty::BorrowKind::from_mutbl(m); + delegate.borrow(pat.hir_id, pat.span, &cmt_pat, r, bk, RefBinding); + } } ty::BindByValue(..) => { - let mode = copy_or_move(mc, param_env, &cmt_pat); + let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove); debug!("walk_pat binding consuming pat"); - delegate.consume(&cmt_pat, mode); + delegate.consume_pat(pat, &cmt_pat, mode); } } } else { @@ -612,6 +879,45 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } })); + + // Do a second pass over the pattern, calling `matched_pat` on + // the interior nodes (enum variants and structs), as opposed + // to the above loop's visit of than the bindings that form + // the leaves of the pattern tree structure. + return_if_err!(mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| { + let qpath = match pat.kind { + PatKind::Path(ref qpath) | + PatKind::TupleStruct(ref qpath, ..) | + PatKind::Struct(ref qpath, ..) => qpath, + _ => return + }; + let res = mc.tables.qpath_res(qpath, pat.hir_id); + match res { + Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_did) => { + let variant_did = mc.tcx.parent(variant_ctor_did).unwrap(); + let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did); + + debug!("variantctor downcast_cmt={:?} pat={:?}", downcast_cmt, pat); + delegate.matched_pat(pat, &downcast_cmt, match_mode); + } + Res::Def(DefKind::Variant, variant_did) => { + let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did); + + debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat); + delegate.matched_pat(pat, &downcast_cmt, match_mode); + } + Res::Def(DefKind::Struct, _) + | Res::Def(DefKind::Ctor(..), _) + | Res::Def(DefKind::Union, _) + | Res::Def(DefKind::TyAlias, _) + | Res::Def(DefKind::AssocTy, _) + | Res::SelfTy(..) => { + debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat); + delegate.matched_pat(pat, &cmt_pat, match_mode); + } + _ => {} + } + })); } fn walk_captures(&mut self, closure_expr: &hir::Expr, fn_decl_span: Span) { @@ -619,7 +925,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { let closure_def_id = self.tcx().hir().local_def_id(closure_expr.hir_id); if let Some(upvars) = self.tcx().upvars(closure_def_id) { - for &var_id in upvars.keys() { + for (&var_id, upvar) in upvars.iter() { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_id }, closure_expr_id: closure_def_id.to_local(), @@ -630,11 +936,19 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { var_id)); match upvar_capture { ty::UpvarCapture::ByValue => { - let mode = copy_or_move(&self.mc, self.param_env, &cmt_var); - self.delegate.consume(&cmt_var, mode); + let mode = copy_or_move(&self.mc, + self.param_env, + &cmt_var, + CaptureMove); + self.delegate.consume(closure_expr.hir_id, upvar.span, &cmt_var, mode); } ty::UpvarCapture::ByRef(upvar_borrow) => { - self.delegate.borrow(&cmt_var, upvar_borrow.kind); + self.delegate.borrow(closure_expr.hir_id, + fn_decl_span, + &cmt_var, + upvar_borrow.region, + upvar_borrow.kind, + ClosureCapture(upvar.span)); } } } @@ -657,9 +971,10 @@ fn copy_or_move<'a, 'tcx>( mc: &mc::MemCategorizationContext<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, cmt: &mc::cmt_<'tcx>, + move_reason: MoveReason, ) -> ConsumeMode { if !mc.type_is_copy_modulo_regions(param_env, cmt.ty, cmt.span) { - Move + Move(move_reason) } else { Copy } diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs similarity index 94% rename from src/librustc_passes/intrinsicck.rs rename to src/librustc/middle/intrinsicck.rs index 91a7e9f5d7fca..c1435551a5918 100644 --- a/src/librustc_passes/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -1,14 +1,14 @@ -use rustc::hir::def::{Res, DefKind}; -use rustc::hir::def_id::DefId; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx}; -use rustc::ty::query::Providers; +use crate::hir::def::{Res, DefKind}; +use crate::hir::def_id::DefId; +use crate::ty::{self, Ty, TyCtxt}; +use crate::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx}; +use crate::ty::query::Providers; use rustc_target::spec::abi::Abi::RustIntrinsic; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use syntax_pos::{Span, sym}; -use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use rustc::hir; +use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use crate::hir; fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: DefId) { tcx.hir().visit_item_likes_in_module( diff --git a/src/librustc_passes/liveness.rs b/src/librustc/middle/liveness.rs similarity index 99% rename from src/librustc_passes/liveness.rs rename to src/librustc/middle/liveness.rs index fb06808619f66..a654a26eb0b76 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -96,17 +96,17 @@ use self::LiveNodeKind::*; use self::VarKind::*; -use rustc::hir; -use rustc::hir::{Expr, HirId}; -use rustc::hir::def::*; -use rustc::hir::def_id::DefId; -use rustc::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; -use rustc::hir::Node; -use rustc::hir::ptr::P; -use rustc::ty::{self, TyCtxt}; -use rustc::ty::query::Providers; -use rustc::lint; -use rustc::util::nodemap::{HirIdMap, HirIdSet}; +use crate::hir; +use crate::hir::{Expr, HirId}; +use crate::hir::def::*; +use crate::hir::def_id::DefId; +use crate::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; +use crate::hir::Node; +use crate::hir::ptr::P; +use crate::ty::{self, TyCtxt}; +use crate::ty::query::Providers; +use crate::lint; +use crate::util::nodemap::{HirIdMap, HirIdSet}; use errors::Applicability; use rustc_data_structures::fx::FxIndexMap; @@ -373,7 +373,7 @@ fn visit_fn<'tcx>( for param in &body.params { let is_shorthand = match param.pat.kind { - rustc::hir::PatKind::Struct(..) => true, + crate::hir::PatKind::Struct(..) => true, _ => false, }; param.pat.each_binding(|_bm, hir_id, _x, ident| { @@ -411,7 +411,7 @@ fn add_from_pat(ir: &mut IrMaps<'_>, pat: &P) { let mut pats = VecDeque::new(); pats.push_back(pat); while let Some(pat) = pats.pop_front() { - use rustc::hir::PatKind::*; + use crate::hir::PatKind::*; match &pat.kind { Binding(.., inner_pat) => { pats.extend(inner_pat.iter()); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index cbf336fdbe2f3..3f5f54c94638e 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -79,11 +79,12 @@ use std::fmt; use std::hash::{Hash, Hasher}; use rustc_data_structures::fx::FxIndexMap; use std::rc::Rc; +use crate::util::nodemap::ItemLocalSet; #[derive(Clone, Debug, PartialEq)] pub enum Categorization<'tcx> { - Rvalue, // temporary val - ThreadLocal, // value that cannot move, but still restricted in scope + Rvalue(ty::Region<'tcx>), // temporary val, argument is its scope + ThreadLocal(ty::Region<'tcx>), // value that cannot move, but still restricted in scope StaticItem, Upvar(Upvar), // upvar referenced by closure env Local(hir::HirId), // local variable @@ -102,7 +103,7 @@ pub struct Upvar { } // different kinds of pointers: -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum PointerKind<'tcx> { /// `Box` Unique, @@ -116,7 +117,7 @@ pub enum PointerKind<'tcx> { // We use the term "interior" to mean "something reachable from the // base without a pointer dereference", e.g., a field -#[derive(Clone, PartialEq)] +#[derive(Clone, Copy, PartialEq, Eq, Hash)] pub enum InteriorKind { InteriorField(FieldIndex), InteriorElement(InteriorOffsetKind), @@ -139,13 +140,13 @@ impl Hash for FieldIndex { } } -#[derive(Clone, PartialEq)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum InteriorOffsetKind { Index, // e.g., `array_expr[index_expr]` Pattern, // e.g., `fn foo([_, a, _, _]: [A; 4]) { ... }` } -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum MutabilityCategory { McImmutable, // Immutable. McDeclared, // Directly declared as mutable. @@ -218,6 +219,7 @@ pub struct MemCategorizationContext<'a, 'tcx> { pub upvars: Option<&'tcx FxIndexMap>, pub region_scope_tree: &'a region::ScopeTree, pub tables: &'a ty::TypeckTables<'tcx>, + rvalue_promotable_map: Option<&'tcx ItemLocalSet>, infcx: Option<&'a InferCtxt<'a, 'tcx>>, } @@ -333,6 +335,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { body_owner: DefId, region_scope_tree: &'a region::ScopeTree, tables: &'a ty::TypeckTables<'tcx>, + rvalue_promotable_map: Option<&'tcx ItemLocalSet>, ) -> MemCategorizationContext<'a, 'tcx> { MemCategorizationContext { tcx, @@ -340,6 +343,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { upvars: tcx.upvars(body_owner), region_scope_tree, tables, + rvalue_promotable_map, infcx: None, param_env, } @@ -365,12 +369,19 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ) -> MemCategorizationContext<'a, 'tcx> { let tcx = infcx.tcx; + // Subtle: we can't do rvalue promotion analysis until the + // typeck phase is complete, which means that you can't trust + // the rvalue lifetimes that result, but that's ok, since we + // don't need to know those during type inference. + let rvalue_promotable_map = None; + MemCategorizationContext { tcx, body_owner, upvars: tcx.upvars(body_owner), region_scope_tree, tables, + rvalue_promotable_map, infcx: Some(infcx), param_env, } @@ -653,7 +664,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { .any(|attr| attr.check_name(sym::thread_local)); let cat = if is_thread_local { - Categorization::ThreadLocal + let re = self.temporary_scope(hir_id.local_id); + Categorization::ThreadLocal(re) } else { Categorization::StaticItem }; @@ -728,18 +740,16 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let ty = self.node_ty(fn_hir_id)?; let kind = match ty.kind { ty::Generator(..) => ty::ClosureKind::FnOnce, - ty::Closure(closure_def_id, substs) => { + ty::Closure(closure_def_id, closure_substs) => { match self.infcx { // During upvar inference we may not know the // closure kind, just use the LATTICE_BOTTOM value. Some(infcx) => - infcx.closure_kind( - closure_def_id, - substs - ).unwrap_or(ty::ClosureKind::LATTICE_BOTTOM), + infcx.closure_kind(closure_def_id, closure_substs) + .unwrap_or(ty::ClosureKind::LATTICE_BOTTOM), None => - substs.as_closure().kind(closure_def_id, self.tcx), + closure_substs.closure_kind(closure_def_id, self.tcx), } } _ => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", ty), @@ -866,6 +876,16 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ret } + /// Returns the lifetime of a temporary created by expr with id `id`. + /// This could be `'static` if `id` is part of a constant expression. + pub fn temporary_scope(&self, id: hir::ItemLocalId) -> ty::Region<'tcx> { + let scope = self.region_scope_tree.temporary_scope(id); + self.tcx.mk_region(match scope { + Some(scope) => ty::ReScope(scope), + None => ty::ReStatic + }) + } + pub fn cat_rvalue_node(&self, hir_id: hir::HirId, span: Span, @@ -874,7 +894,28 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { debug!("cat_rvalue_node(id={:?}, span={:?}, expr_ty={:?})", hir_id, span, expr_ty); - let ret = self.cat_rvalue(hir_id, span, expr_ty); + let promotable = self.rvalue_promotable_map.as_ref().map(|m| m.contains(&hir_id.local_id)) + .unwrap_or(false); + + debug!("cat_rvalue_node: promotable = {:?}", promotable); + + // Always promote `[T; 0]` (even when e.g., borrowed mutably). + let promotable = match expr_ty.kind { + ty::Array(_, len) if len.try_eval_usize(self.tcx, self.param_env) == Some(0) => true, + _ => promotable, + }; + + debug!("cat_rvalue_node: promotable = {:?} (2)", promotable); + + // Compute maximum lifetime of this rvalue. This is 'static if + // we can promote to a constant, otherwise equal to enclosing temp + // lifetime. + let re = if promotable { + self.tcx.lifetimes.re_static + } else { + self.temporary_scope(hir_id.local_id) + }; + let ret = self.cat_rvalue(hir_id, span, re, expr_ty); debug!("cat_rvalue_node ret {:?}", ret); ret } @@ -882,11 +923,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { pub fn cat_rvalue(&self, cmt_hir_id: hir::HirId, span: Span, + temp_scope: ty::Region<'tcx>, expr_ty: Ty<'tcx>) -> cmt_<'tcx> { let ret = cmt_ { hir_id: cmt_hir_id, span:span, - cat:Categorization::Rvalue, + cat:Categorization::Rvalue(temp_scope), mutbl:McDeclared, ty:expr_ty, note: NoteNone @@ -1334,9 +1376,9 @@ impl<'tcx> cmt_<'tcx> { //! determines how long the value in `self` remains live. match self.cat { - Categorization::Rvalue | + Categorization::Rvalue(..) | Categorization::StaticItem | - Categorization::ThreadLocal | + Categorization::ThreadLocal(..) | Categorization::Local(..) | Categorization::Deref(_, UnsafePtr(..)) | Categorization::Deref(_, BorrowedPtr(..)) | @@ -1367,8 +1409,8 @@ impl<'tcx> cmt_<'tcx> { b.freely_aliasable() } - Categorization::Rvalue | - Categorization::ThreadLocal | + Categorization::Rvalue(..) | + Categorization::ThreadLocal(..) | Categorization::Local(..) | Categorization::Upvar(..) | Categorization::Deref(_, UnsafePtr(..)) => { // yes, it's aliasable, but... @@ -1415,10 +1457,10 @@ impl<'tcx> cmt_<'tcx> { Categorization::StaticItem => { "static item".into() } - Categorization::ThreadLocal => { + Categorization::ThreadLocal(..) => { "thread-local static item".into() } - Categorization::Rvalue => { + Categorization::Rvalue(..) => { "non-place".into() } Categorization::Local(vid) => { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 9ff205228a566..28bf88321ae66 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -16,8 +16,8 @@ use crate::util::nodemap::{FxHashMap, FxHashSet}; use crate::ty::{self, DefIdTree, TyCtxt}; use crate::ty::query::Providers; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_index::vec::Idx; +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}; @@ -131,7 +131,7 @@ pub enum ScopeData { Remainder(FirstStatementIndex) } -rustc_index::newtype_index! { +newtype_index! { /// Represents a subscope of `block` for a binding that is introduced /// by `block.stmts[first_statement_index]`. Such subscopes represent /// a suffix of the block. Note that each subscope does not include @@ -1491,7 +1491,9 @@ pub fn provide(providers: &mut Providers<'_>) { } impl<'a> HashStable> for ScopeTree { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let ScopeTree { root_body, root_parent, diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index a122d84a5aa7e..94a85a97d36c9 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -708,22 +708,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { match param.kind { GenericParamKind::Lifetime { .. } => { let (name, reg) = Region::early(&self.tcx.hir(), &mut index, ¶m); - let def_id = if let Region::EarlyBound(_ ,def_id , _) = reg { - def_id - } else { - bug!(); - }; if let hir::ParamName::Plain(param_name) = name { if param_name.name == kw::UnderscoreLifetime { // Pick the elided lifetime "definition" if one exists // and use it to make an elision scope. - self.lifetime_uses.insert(def_id.clone(), LifetimeUseSet::Many); elision = Some(reg); } else { lifetimes.insert(name, reg); } } else { - self.lifetime_uses.insert(def_id.clone(), LifetimeUseSet::Many); lifetimes.insert(name, reg); } } @@ -771,6 +764,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }); } } + hir::TyKind::CVarArgs(ref lt) => { + // Resolve the generated lifetime for the C-variadic arguments. + // The lifetime is generated in AST -> HIR lowering. + if lt.name.is_elided() { + self.resolve_elided_lifetimes(vec![lt]) + } + } _ => intravisit::walk_ty(self, ty), } } @@ -1622,6 +1622,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { _ => None, } { debug!("id = {:?} span = {:?} name = {:?}", id, span, name); + if name.name == kw::UnderscoreLifetime { continue; } @@ -2377,6 +2378,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { self.visit_lifetime(lifetime); } } + hir::TyKind::CVarArgs(_) => {} _ => { intravisit::walk_ty(self, ty); } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index e65f17c79497e..30a88d155f5f8 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -25,7 +25,7 @@ use crate::util::nodemap::{FxHashSet, FxHashMap}; use std::mem::replace; use std::cmp::Ordering; -#[derive(PartialEq, Clone, Copy, Debug)] +#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Copy, Debug, Eq, Hash)] pub enum StabilityLevel { Unstable, Stable, @@ -485,13 +485,7 @@ pub fn provide(providers: &mut Providers<'_>) { } pub fn report_unstable( - sess: &Session, - feature: Symbol, - reason: Option, - issue: u32, - is_soft: bool, - span: Span, - soft_handler: impl FnOnce(&'static lint::Lint, Span, &str), + sess: &Session, feature: Symbol, reason: Option, issue: u32, is_soft: bool, span: Span ) { let msg = match reason { Some(r) => format!("use of unstable library feature '{}': {}", feature, r), @@ -517,7 +511,7 @@ pub fn report_unstable( let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id); if fresh { if is_soft { - soft_handler(lint::builtin::SOFT_UNSTABLE, span, &msg) + sess.buffer_lint(lint::builtin::SOFT_UNSTABLE, CRATE_NODE_ID, span, &msg); } else { emit_feature_err( &sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg @@ -785,12 +779,10 @@ impl<'tcx> TyCtxt<'tcx> { /// Additionally, this function will also check if the item is deprecated. If so, and `id` is /// not `None`, a deprecated lint attached to `id` will be emitted. pub fn check_stability(self, def_id: DefId, id: Option, span: Span) { - let soft_handler = - |lint, span, msg: &_| self.lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg); match self.eval_stability(def_id, id, span) { EvalResult::Allow => {} EvalResult::Deny { feature, reason, issue, is_soft } => - report_unstable(self.sess, feature, reason, issue, is_soft, span, soft_handler), + report_unstable(self.sess, feature, reason, issue, is_soft, span), EvalResult::Unmarked => { // The API could be uncallable for other reasons, for example when a private module // was referenced. @@ -905,10 +897,11 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { // Warn if the user has enabled an already-stable lang feature. unnecessary_stable_feature_lint(tcx, span, feature, since); } - if !lang_features.insert(feature) { + if lang_features.contains(&feature) { // Warn if the user enables a lang feature multiple times. duplicate_feature_err(tcx.sess, span, feature); } + lang_features.insert(feature); } let declared_lib_features = &tcx.features().declared_lib_features; diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 9b41366741876..1f604877841a7 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -1,6 +1,6 @@ -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::{RwLock, MappedReadGuard, ReadGuard}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; use crate::ich::StableHashingContext; use crate::mir::{Body, BasicBlock}; @@ -24,7 +24,9 @@ impl rustc_serialize::Decodable for Cache { } impl<'a> HashStable> for Cache { - fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { + fn hash_stable(&self, + _: &mut StableHashingContext<'a>, + _: &mut StableHasher) { // Do nothing. } } diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index aa8ac4902a894..15e6cb6bcabae 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -245,8 +245,6 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// as a slice. /// /// It is the caller's responsibility to check bounds and alignment beforehand. - /// Most likely, you want to use the `PlaceTy` and `OperandTy`-based methods - /// on `InterpCx` instead. #[inline] pub fn get_bytes( &self, @@ -277,8 +275,6 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// so be sure to actually put data there! /// /// It is the caller's responsibility to check bounds and alignment beforehand. - /// Most likely, you want to use the `PlaceTy` and `OperandTy`-based methods - /// on `InterpCx` instead. pub fn get_bytes_mut( &mut self, cx: &impl HasDataLayout, @@ -301,8 +297,6 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { 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. - /// - /// Most likely, you want to call `Memory::read_c_str` instead of this method. pub fn read_c_str( &self, cx: &impl HasDataLayout, @@ -348,25 +342,33 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Writes `src` to the memory starting at `ptr.offset`. /// /// It is the caller's responsibility to check bounds and alignment beforehand. - /// Most likely, you want to call `Memory::write_bytes` instead of this method. pub fn write_bytes( &mut self, cx: &impl HasDataLayout, ptr: Pointer, - src: impl IntoIterator, + src: &[u8], + ) -> InterpResult<'tcx> + { + let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64))?; + bytes.clone_from_slice(src); + Ok(()) + } + + /// Sets `count` bytes starting at `ptr.offset` with `val`. Basically `memset`. + /// + /// It is the caller's responsibility to check bounds and alignment beforehand. + pub fn write_repeat( + &mut self, + cx: &impl HasDataLayout, + ptr: Pointer, + val: u8, + count: Size ) -> InterpResult<'tcx> { - let mut src = src.into_iter(); - let (lower, upper) = src.size_hint(); - let len = upper.expect("can only write bounded iterators"); - assert_eq!(lower, len, "can only write iterators with a precise length"); - let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(len as u64))?; - // `zip` would stop when the first iterator ends; we want to definitely - // cover all of `bytes`. - for dest in bytes { - *dest = src.next().expect("iterator was shorter than it said it would be"); + let bytes = self.get_bytes_mut(cx, ptr, count)?; + for b in bytes { + *b = val; } - src.next().expect_none("iterator was longer than it said it would be"); Ok(()) } @@ -378,7 +380,6 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// pointers being valid for ZSTs. /// /// It is the caller's responsibility to check bounds and alignment beforehand. - /// Most likely, you want to call `InterpCx::read_scalar` instead of this method. pub fn read_scalar( &self, cx: &impl HasDataLayout, @@ -417,7 +418,6 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Reads a pointer-sized scalar. /// /// It is the caller's responsibility to check bounds and alignment beforehand. - /// Most likely, you want to call `InterpCx::read_scalar` instead of this method. pub fn read_ptr_sized( &self, cx: &impl HasDataLayout, @@ -435,7 +435,6 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// pointers being valid for ZSTs. /// /// It is the caller's responsibility to check bounds and alignment beforehand. - /// Most likely, you want to call `InterpCx::write_scalar` instead of this method. pub fn write_scalar( &mut self, cx: &impl HasDataLayout, @@ -478,7 +477,6 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Writes a pointer-sized scalar. /// /// It is the caller's responsibility to check bounds and alignment beforehand. - /// Most likely, you want to call `InterpCx::write_scalar` instead of this method. pub fn write_ptr_sized( &mut self, cx: &impl HasDataLayout, diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index d918b9ee67347..71967b513a049 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -363,8 +363,6 @@ pub enum UndefinedBehaviorInfo { UbExperimental(String), /// Unreachable code was executed. Unreachable, - /// An enum discriminant was set to a value which was outside the range of valid values. - InvalidDiscriminant(ScalarMaybeUndef), } impl fmt::Debug for UndefinedBehaviorInfo { @@ -375,8 +373,6 @@ impl fmt::Debug for UndefinedBehaviorInfo { write!(f, "{}", msg), Unreachable => write!(f, "entered unreachable code"), - InvalidDiscriminant(val) => - write!(f, "encountered invalid enum discriminant {}", val), } } } @@ -393,6 +389,10 @@ pub enum UnsupportedOpInfo<'tcx> { /// Free-form case. Only for errors that are never caught! Unsupported(String), + /// FIXME(#64506) Error used to work around accessing projections of + /// uninhabited types. + UninhabitedValue, + // -- Everything below is not categorized yet -- FunctionAbiMismatch(Abi, Abi), FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>), @@ -404,6 +404,7 @@ pub enum UnsupportedOpInfo<'tcx> { InvalidMemoryAccess, InvalidFunctionPointer, InvalidBool, + InvalidDiscriminant(ScalarMaybeUndef), PointerOutOfBounds { ptr: Pointer, msg: CheckInAllocMsg, @@ -488,6 +489,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { write!(f, "incorrect alloc info: expected size {} and align {}, \ got size {} and align {}", size.bytes(), align.bytes(), size2.bytes(), align2.bytes()), + InvalidDiscriminant(val) => + write!(f, "encountered invalid enum discriminant {}", val), InvalidMemoryAccess => write!(f, "tried to access memory through an invalid pointer"), DanglingPointerDeref => @@ -553,6 +556,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { not a power of two"), Unsupported(ref msg) => write!(f, "{}", msg), + UninhabitedValue => + write!(f, "tried to use an uninhabited value"), } } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 6c31d54e081c4..cd58396d95c62 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -101,7 +101,7 @@ pub use self::error::{ InvalidProgramInfo, ResourceExhaustionInfo, UndefinedBehaviorInfo, }; -pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue, get_slice_bytes}; +pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue}; pub use self::allocation::{Allocation, AllocationExtra, Relocations, UndefMask}; @@ -470,14 +470,6 @@ impl<'tcx> AllocMap<'tcx> { } } - /// Panics if the `AllocId` does not refer to a function - pub fn unwrap_fn(&self, id: AllocId) -> Instance<'tcx> { - match self.get(id) { - Some(GlobalAlloc::Function(instance)) => instance, - _ => bug!("expected allocation ID {} to point to a function", id), - } - } - /// 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) { diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index ac16b8b884c45..b8bc741419738 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -5,12 +5,11 @@ use rustc_apfloat::{Float, ieee::{Double, Single}}; use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}, subst::SubstsRef}; use crate::ty::PlaceholderConst; use crate::hir::def_id::DefId; -use crate::ty::{BoundVar, DebruijnIndex}; use super::{InterpResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate}; /// Represents the result of a raw const operation, pre-validation. -#[derive(Clone, HashStable)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash, HashStable)] pub struct RawConst<'tcx> { // the value lives here, at offset 0, and that allocation definitely is a `AllocKind::Memory` // (so you can use `AllocMap::unwrap_memory`). @@ -29,9 +28,6 @@ pub enum ConstValue<'tcx> { /// Infer the value of the const. Infer(InferConst<'tcx>), - /// Bound const variable, used only when preparing a trait query. - Bound(DebruijnIndex, BoundVar), - /// A placeholder const - universally quantified higher-ranked const. Placeholder(PlaceholderConst), @@ -70,9 +66,8 @@ impl<'tcx> ConstValue<'tcx> { match *self { ConstValue::Param(_) | ConstValue::Infer(_) | - ConstValue::Bound(..) | ConstValue::Placeholder(_) | - ConstValue::ByRef { .. } | + ConstValue::ByRef{ .. } | ConstValue::Unevaluated(..) | ConstValue::Slice { .. } => None, ConstValue::Scalar(val) => Some(val), @@ -348,19 +343,14 @@ impl<'tcx, Tag> Scalar { } } - #[inline(always)] - pub fn check_raw(data: u128, size: u8, target_size: Size) { - assert_eq!(target_size.bytes(), size as u64); - assert_ne!(size, 0, "you should never look at the bits of a ZST"); - Scalar::check_data(data, size); - } - /// Do not call this method! Use either `assert_bits` or `force_bits`. #[inline] pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> { match self { Scalar::Raw { data, size } => { - Self::check_raw(data, size, target_size); + assert_eq!(target_size.bytes(), size as u64); + assert_ne!(size, 0, "you should never look at the bits of a ZST"); + Scalar::check_data(data, size); Ok(data) } Scalar::Ptr(_) => throw_unsup!(ReadPointerAsBytes), @@ -492,7 +482,7 @@ impl From> for Scalar { } } -#[derive(Clone, Copy, Eq, PartialEq, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, RustcEncodable, RustcDecodable)] pub enum ScalarMaybeUndef { Scalar(Scalar), Undef, @@ -621,18 +611,3 @@ impl_stable_hash_for!(enum crate::mir::interpret::ScalarMaybeUndef { Scalar(v), Undef }); - -/// Gets the bytes of a constant slice value. -pub fn get_slice_bytes<'tcx>(cx: &impl HasDataLayout, val: ConstValue<'tcx>) -> &'tcx [u8] { - if let ConstValue::Slice { data, start, end } = val { - let len = end - start; - data.get_bytes( - cx, - // invent a pointer, only the offset is relevant anyway - Pointer::new(AllocId(0), Size::from_bytes(start as u64)), - Size::from_bytes(len as u64), - ).unwrap_or_else(|err| bug!("const slice is invalid: {:?}", err)) - } else { - bug!("expected const slice, but found another const value"); - } -} diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index fb9c95724c955..cf82184ab032c 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -15,15 +15,16 @@ use crate::ty::layout::VariantIdx; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{ - self, AdtDef, CanonicalUserTypeAnnotations, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex, + self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt, + UserTypeAnnotationIndex, }; use polonius_engine::Atom; -use rustc_index::bit_set::BitMatrix; +use rustc_data_structures::bit_set::BitMatrix; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::dominators::{dominators, Dominators}; use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors}; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::MappedReadGuard; use rustc_macros::HashStable; @@ -36,7 +37,7 @@ use std::slice; use std::vec::IntoIter; use std::{iter, mem, option, u32}; use syntax::ast::Name; -use syntax::symbol::Symbol; +use syntax::symbol::{InternedString, Symbol}; use syntax_pos::{Span, DUMMY_SP}; pub use crate::mir::interpret::AssertMessage; @@ -467,7 +468,7 @@ impl rustc_serialize::UseSpecializedDecodable for ClearCrossCrate< /// Grouped information about the source code origin of a MIR entity. /// Intended to be inspected by diagnostics and debuginfo. /// Most passes can work with it as a whole, within a single function. -#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, HashStable)] pub struct SourceInfo { /// The source span for the AST pertaining to this MIR entity. pub span: Span, @@ -580,7 +581,7 @@ impl BorrowKind { /////////////////////////////////////////////////////////////////////////// // Variables and temps -rustc_index::newtype_index! { +newtype_index! { pub struct Local { derive [HashStable] DEBUG_FORMAT = "_{}", @@ -607,7 +608,7 @@ pub enum LocalKind { ReturnPointer, } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct VarBindingForm<'tcx> { /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`? pub binding_mode: ty::BindingMode, @@ -629,7 +630,7 @@ pub struct VarBindingForm<'tcx> { pub pat_span: Span, } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum BindingForm<'tcx> { /// This is a binding for a non-`self` binding, or a `self` that has an explicit type. Var(VarBindingForm<'tcx>), @@ -640,7 +641,7 @@ pub enum BindingForm<'tcx> { } /// Represents what type of implicit self a function has, if any. -#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum ImplicitSelfKind { /// Represents a `fn x(self);`. Imm, @@ -681,10 +682,14 @@ impl_stable_hash_for!(enum self::MirPhase { mod binding_form_impl { use crate::ich::StableHashingContext; - use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; + use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; impl<'a, 'tcx> HashStable> for super::BindingForm<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher, + ) { use super::BindingForm::*; ::std::mem::discriminant(self).hash_stable(hcx, hasher); @@ -993,7 +998,7 @@ pub struct UpvarDebuginfo { /////////////////////////////////////////////////////////////////////////// // BasicBlock -rustc_index::newtype_index! { +newtype_index! { pub struct BasicBlock { derive [HashStable] DEBUG_FORMAT = "bb{}", @@ -1711,17 +1716,15 @@ impl Debug for Statement<'_> { /// A path to a value; something that can be evaluated without /// changing or disturbing program state. #[derive( - Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, HashStable, + Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable, )] pub struct Place<'tcx> { pub base: PlaceBase<'tcx>, /// projection out of a place (access a field, deref a pointer, etc) - pub projection: &'tcx List>, + pub projection: Box<[PlaceElem<'tcx>]>, } -impl<'tcx> rustc_serialize::UseSpecializedDecodable for Place<'tcx> {} - #[derive( Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable, )] @@ -1825,8 +1828,6 @@ impl ProjectionElem { /// and the index is a local. pub type PlaceElem<'tcx> = ProjectionElem>; -impl<'tcx> Copy for PlaceElem<'tcx> { } - // At least on 64 bit systems, `PlaceElem` should not be larger than two pointers. #[cfg(target_arch = "x86_64")] static_assert_size!(PlaceElem<'_>, 16); @@ -1835,7 +1836,7 @@ static_assert_size!(PlaceElem<'_>, 16); /// need neither the `V` parameter for `Index` nor the `T` for `Field`. pub type ProjectionKind = ProjectionElem<(), ()>; -rustc_index::newtype_index! { +newtype_index! { pub struct Field { derive [HashStable] DEBUG_FORMAT = "field[{}]" @@ -1849,11 +1850,50 @@ pub struct PlaceRef<'a, 'tcx> { } impl<'tcx> Place<'tcx> { - // FIXME change this to a const fn by also making List::empty a const fn. + // 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: List::empty(), + projection: Box::new([]), + } + } + + pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> { + self.elem(ProjectionElem::Field(f, ty)) + } + + pub fn deref(self) -> Place<'tcx> { + self.elem(ProjectionElem::Deref) + } + + pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> { + self.elem(ProjectionElem::Downcast( + Some(adt_def.variants[variant_index].ident.name), + variant_index, + )) + } + + pub fn downcast_unnamed(self, variant_index: VariantIdx) -> Place<'tcx> { + self.elem(ProjectionElem::Downcast(None, variant_index)) + } + + pub fn index(self, index: Local) -> Place<'tcx> { + self.elem(ProjectionElem::Index(index)) + } + + 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: projection.into_boxed_slice(), } } @@ -1870,15 +1910,15 @@ impl<'tcx> Place<'tcx> { // // FIXME: can we safely swap the semantics of `fn base_local` below in here instead? pub fn local_or_deref_local(&self) -> Option { - match self.as_ref() { - PlaceRef { - base: &PlaceBase::Local(local), - projection: &[], + match self { + Place { + base: PlaceBase::Local(local), + projection: box [], } | - PlaceRef { - base: &PlaceBase::Local(local), - projection: &[ProjectionElem::Deref], - } => Some(local), + Place { + base: PlaceBase::Local(local), + projection: box [ProjectionElem::Deref], + } => Some(*local), _ => None, } } @@ -1886,7 +1926,10 @@ impl<'tcx> Place<'tcx> { /// If this place represents a local variable like `_X` with no /// projections, return `Some(_X)`. pub fn as_local(&self) -> Option { - self.as_ref().as_local() + match self { + Place { projection: box [], base: PlaceBase::Local(l) } => Some(*l), + _ => None, + } } pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> { @@ -1901,7 +1944,7 @@ impl From for Place<'_> { fn from(local: Local) -> Self { Place { base: local.into(), - projection: List::empty(), + projection: Box::new([]), } } } @@ -1930,15 +1973,6 @@ impl<'a, 'tcx> PlaceRef<'a, 'tcx> { _ => None, } } - - /// If this place represents a local variable like `_X` with no - /// projections, return `Some(_X)`. - pub fn as_local(&self) -> Option { - match self { - PlaceRef { base: PlaceBase::Local(l), projection: [] } => Some(*l), - _ => None, - } - } } impl Debug for Place<'_> { @@ -2017,7 +2051,7 @@ impl Debug for PlaceBase<'_> { /////////////////////////////////////////////////////////////////////////// // Scopes -rustc_index::newtype_index! { +newtype_index! { pub struct SourceScope { derive [HashStable] DEBUG_FORMAT = "scope[{}]", @@ -2158,8 +2192,8 @@ pub enum AggregateKind<'tcx> { /// active field index would identity the field `c` Adt(&'tcx AdtDef, VariantIdx, SubstsRef<'tcx>, Option, Option), - Closure(DefId, SubstsRef<'tcx>), - Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability), + Closure(DefId, ClosureSubsts<'tcx>), + Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), } #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] @@ -2362,7 +2396,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { /// this does not necessarily mean that they are "==" in Rust -- in /// particular one must be wary of `NaN`! -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct Constant<'tcx> { pub span: Span, @@ -2408,7 +2442,7 @@ pub struct Constant<'tcx> { /// The first will lead to the constraint `w: &'1 str` (for some /// inferred region `'1`). The second will lead to the constraint `w: /// &'static str`. -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct UserTypeProjections { pub(crate) contents: Vec<(UserTypeProjection, Span)>, } @@ -2485,7 +2519,7 @@ impl<'tcx> UserTypeProjections { /// * `let (x, _): T = ...` -- here, the `projs` vector would contain /// `field[0]` (aka `.0`), indicating that the type of `s` is /// determined by finding the type of the `.0` field from `T`. -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct UserTypeProjection { pub base: UserTypeAnnotationIndex, pub projs: Vec, @@ -2556,7 +2590,7 @@ impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection { } } -rustc_index::newtype_index! { +newtype_index! { pub struct Promoted { derive [HashStable] DEBUG_FORMAT = "promoted[{}]" @@ -2572,14 +2606,7 @@ impl<'tcx> Debug for Constant<'tcx> { impl<'tcx> Display for Constant<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { write!(fmt, "const ")?; - // FIXME make the default pretty printing of raw pointers more detailed. Here we output the - // debug representation of raw pointers, so that the raw pointers in the mir dump output are - // detailed and just not '{pointer}'. - if let ty::RawPtr(_) = self.literal.ty.kind { - write!(fmt, "{:?} : {}", self.literal.val, self.literal.ty) - } else { - write!(fmt, "{}", self.literal) - } + write!(fmt, "{}", self.literal) } } @@ -2694,7 +2721,7 @@ impl Location { } } -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub enum UnsafetyViolationKind { General, /// Permitted both in `const fn`s and regular `fn`s. @@ -2703,15 +2730,15 @@ pub enum UnsafetyViolationKind { BorrowPacked(hir::HirId), } -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct UnsafetyViolation { pub source_info: SourceInfo, - pub description: Symbol, - pub details: Symbol, + pub description: InternedString, + pub details: InternedString, pub kind: UnsafetyViolationKind, } -#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct UnsafetyCheckResult { /// Violations that are propagated *upwards* from this function. pub violations: Lrc<[UnsafetyViolation]>, @@ -2720,7 +2747,7 @@ pub struct UnsafetyCheckResult { pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>, } -rustc_index::newtype_index! { +newtype_index! { pub struct GeneratorSavedLocal { derive [HashStable] DEBUG_FORMAT = "_{}", @@ -3152,17 +3179,6 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceBase<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - let v = self.iter().map(|t| t.fold_with(folder)).collect::>(); - folder.tcx().intern_place_elems(&v) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) - } -} - impl<'tcx> TypeFoldable<'tcx> for Static<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { Static { diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index 58f99667cb3a4..a061e6f48f4c0 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -1,6 +1,6 @@ use crate::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; use crate::hir::HirId; -use syntax::symbol::Symbol; +use syntax::symbol::InternedString; use syntax::attr::InlineAttr; use syntax::source_map::Span; use crate::ty::{Instance, InstanceDef, TyCtxt, SymbolName, subst::InternalSubsts}; @@ -8,14 +8,15 @@ use crate::util::nodemap::FxHashMap; use crate::ty::print::obsolete::DefPathBasedNames; use crate::dep_graph::{WorkProductId, DepNode, WorkProduct, DepConstructor}; use rustc_data_structures::base_n; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasherResult, + StableHasher}; use crate::ich::{Fingerprint, StableHashingContext, NodeIdHashingMode}; use crate::session::config::OptLevel; use std::fmt; use std::hash::Hash; /// Describes how a monomorphization will be instantiated in object files. -#[derive(PartialEq)] +#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] pub enum InstantiationMode { /// There will be exactly one instance of the given MonoItem. It will have /// external linkage so that it can be linked to from other codegen units. @@ -80,7 +81,7 @@ impl<'tcx> MonoItem<'tcx> { MonoItem::GlobalAsm(hir_id) => { let def_id = tcx.hir().local_def_id(hir_id); SymbolName { - name: Symbol::intern(&format!("global_asm_{:?}", def_id)) + name: InternedString::intern(&format!("global_asm_{:?}", def_id)) } } } @@ -222,7 +223,9 @@ impl<'tcx> MonoItem<'tcx> { } impl<'a, 'tcx> HashStable> for MonoItem<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { ::std::mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -246,12 +249,12 @@ pub struct CodegenUnit<'tcx> { /// name be unique amongst **all** crates. Therefore, it should /// contain something unique to this crate (e.g., a module path) /// as well as the crate name and disambiguator. - name: Symbol, + name: InternedString, items: FxHashMap, (Linkage, Visibility)>, size_estimate: Option, } -#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum Linkage { External, AvailableExternally, @@ -280,7 +283,7 @@ impl_stable_hash_for!(enum self::Linkage { Common }); -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum Visibility { Default, Hidden, @@ -294,7 +297,7 @@ impl_stable_hash_for!(enum self::Visibility { }); impl<'tcx> CodegenUnit<'tcx> { - pub fn new(name: Symbol) -> CodegenUnit<'tcx> { + pub fn new(name: InternedString) -> CodegenUnit<'tcx> { CodegenUnit { name: name, items: Default::default(), @@ -302,11 +305,11 @@ impl<'tcx> CodegenUnit<'tcx> { } } - pub fn name(&self) -> Symbol { - self.name + pub fn name(&self) -> &InternedString { + &self.name } - pub fn set_name(&mut self, name: Symbol) { + pub fn set_name(&mut self, name: InternedString) { self.name = name; } @@ -386,7 +389,6 @@ impl<'tcx> CodegenUnit<'tcx> { tcx.hir().as_local_hir_id(def_id) } InstanceDef::VtableShim(..) | - InstanceDef::ReifyShim(..) | InstanceDef::Intrinsic(..) | InstanceDef::FnPtrShim(..) | InstanceDef::Virtual(..) | @@ -417,7 +419,9 @@ impl<'tcx> CodegenUnit<'tcx> { } impl<'a, 'tcx> HashStable> for CodegenUnit<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let CodegenUnit { ref items, name, @@ -474,7 +478,7 @@ impl CodegenUnitNameBuilder<'tcx> { cnum: CrateNum, components: I, special_suffix: Option) - -> Symbol + -> InternedString where I: IntoIterator, C: fmt::Display, S: fmt::Display, @@ -487,7 +491,7 @@ impl CodegenUnitNameBuilder<'tcx> { cgu_name } else { let cgu_name = &cgu_name.as_str()[..]; - Symbol::intern(&CodegenUnit::mangle_name(cgu_name)) + InternedString::intern(&CodegenUnit::mangle_name(cgu_name)) } } @@ -497,7 +501,7 @@ impl CodegenUnitNameBuilder<'tcx> { cnum: CrateNum, components: I, special_suffix: Option) - -> Symbol + -> InternedString where I: IntoIterator, C: fmt::Display, S: fmt::Display, @@ -543,6 +547,6 @@ impl CodegenUnitNameBuilder<'tcx> { write!(cgu_name, ".{}", special_suffix).unwrap(); } - Symbol::intern(&cgu_name[..]) + InternedString::intern(&cgu_name[..]) } } diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index e87aabf9a0566..26f718e858da8 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -197,7 +197,7 @@ impl<'tcx> Rvalue<'tcx> { let ty = place.ty(local_decls, tcx).ty; match ty.kind { ty::Adt(adt_def, _) => adt_def.repr.discr_type().to_ty(tcx), - ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx), + ty::Generator(_, substs, _) => substs.discr_ty(tcx), _ => { // This can only be `0`, for now, so `u8` will suffice. tcx.types.u8 diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index f129dd3abeff7..1416a5f0a6e9f 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -1,4 +1,4 @@ -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use super::*; diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 6a41b843e5794..1e3b9eb29c79d 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -1,5 +1,5 @@ use crate::ty::subst::SubstsRef; -use crate::ty::{CanonicalUserTypeAnnotation, Ty}; +use crate::ty::{CanonicalUserTypeAnnotation, ClosureSubsts, GeneratorSubsts, Ty}; use crate::mir::*; use syntax_pos::Span; @@ -158,7 +158,13 @@ macro_rules! make_mir_visitor { self.super_place_base(base, context, location); } - visit_place_fns!($($mutability)?); + fn visit_projection(&mut self, + base: & $($mutability)? PlaceBase<'tcx>, + projection: & $($mutability)? [PlaceElem<'tcx>], + context: PlaceContext, + location: Location) { + self.super_projection(base, projection, context, location); + } fn visit_constant(&mut self, constant: & $($mutability)? Constant<'tcx>, @@ -215,6 +221,18 @@ macro_rules! make_mir_visitor { self.super_substs(substs); } + fn visit_closure_substs(&mut self, + substs: & $($mutability)? ClosureSubsts<'tcx>, + _: Location) { + self.super_closure_substs(substs); + } + + fn visit_generator_substs(&mut self, + substs: & $($mutability)? GeneratorSubsts<'tcx>, + _: Location) { + self.super_generator_substs(substs); + } + fn visit_local_decl(&mut self, local: Local, local_decl: & $($mutability)? LocalDecl<'tcx>) { @@ -600,14 +618,14 @@ macro_rules! make_mir_visitor { _, closure_substs ) => { - self.visit_substs(closure_substs, location); + self.visit_closure_substs(closure_substs, location); } AggregateKind::Generator( _, generator_substs, _movability, ) => { - self.visit_substs(generator_substs, location); + self.visit_generator_substs(generator_substs, location); } } @@ -666,6 +684,28 @@ macro_rules! make_mir_visitor { ); } + fn super_place(&mut self, + place: & $($mutability)? Place<'tcx>, + context: PlaceContext, + location: Location) { + let mut context = context; + + if !place.projection.is_empty() { + context = if context.is_mutating_use() { + PlaceContext::MutatingUse(MutatingUseContext::Projection) + } else { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) + }; + } + + self.visit_place_base(& $($mutability)? place.base, context, location); + + self.visit_projection(& $($mutability)? place.base, + & $($mutability)? place.projection, + context, + location); + } + fn super_place_base(&mut self, place_base: & $($mutability)? PlaceBase<'tcx>, context: PlaceContext, @@ -680,6 +720,36 @@ macro_rules! make_mir_visitor { } } + fn super_projection(&mut self, + base: & $($mutability)? PlaceBase<'tcx>, + projection: & $($mutability)? [PlaceElem<'tcx>], + context: PlaceContext, + location: Location) { + if let [proj_base @ .., elem] = projection { + self.visit_projection(base, proj_base, context, location); + + 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(_, _) => { + } + } + } + } + fn super_local_decl(&mut self, local: Local, local_decl: & $($mutability)? LocalDecl<'tcx>) { @@ -764,6 +834,14 @@ macro_rules! make_mir_visitor { fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) { } + fn super_generator_substs(&mut self, + _substs: & $($mutability)? GeneratorSubsts<'tcx>) { + } + + fn super_closure_substs(&mut self, + _substs: & $($mutability)? ClosureSubsts<'tcx>) { + } + // Convenience methods fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) { @@ -782,145 +860,6 @@ macro_rules! make_mir_visitor { } } -macro_rules! visit_place_fns { - (mut) => ( - fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; - - fn super_place( - &mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location, - ) { - self.visit_place_base(&mut place.base, context, location); - - if let Some(new_projection) = self.process_projection(&place.projection) { - place.projection = self.tcx().intern_place_elems(&new_projection); - } - } - - fn process_projection( - &mut self, - projection: &'a [PlaceElem<'tcx>], - ) -> Option>> { - let mut projection = Cow::Borrowed(projection); - - for i in 0..projection.len() { - if let Some(elem) = projection.get(i) { - if let Some(elem) = self.process_projection_elem(elem) { - // This converts the borrowed projection into `Cow::Owned(_)` and returns a - // clone of the projection so we can mutate and reintern later. - let vec = projection.to_mut(); - vec[i] = elem; - } - } - } - - match projection { - Cow::Borrowed(_) => None, - Cow::Owned(vec) => Some(vec), - } - } - - fn process_projection_elem( - &mut self, - _elem: &PlaceElem<'tcx>, - ) -> Option> { - None - } - ); - - () => ( - fn visit_projection( - &mut self, - base: &PlaceBase<'tcx>, - projection: &[PlaceElem<'tcx>], - context: PlaceContext, - location: Location, - ) { - self.super_projection(base, projection, context, location); - } - - fn visit_projection_elem( - &mut self, - base: &PlaceBase<'tcx>, - proj_base: &[PlaceElem<'tcx>], - elem: &PlaceElem<'tcx>, - context: PlaceContext, - location: Location, - ) { - self.super_projection_elem(base, proj_base, elem, context, location); - } - - fn super_place( - &mut self, - place: &Place<'tcx>, - context: PlaceContext, - location: Location, - ) { - let mut context = context; - - if !place.projection.is_empty() { - context = if context.is_mutating_use() { - PlaceContext::MutatingUse(MutatingUseContext::Projection) - } else { - PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) - }; - } - - self.visit_place_base(&place.base, context, location); - - self.visit_projection(&place.base, - &place.projection, - context, - location); - } - - fn super_projection( - &mut self, - base: &PlaceBase<'tcx>, - projection: &[PlaceElem<'tcx>], - context: PlaceContext, - location: Location, - ) { - let mut cursor = projection; - while let [proj_base @ .., elem] = cursor { - cursor = proj_base; - self.visit_projection_elem(base, cursor, elem, context, location); - } - } - - fn super_projection_elem( - &mut self, - _base: &PlaceBase<'tcx>, - _proj_base: &[PlaceElem<'tcx>], - elem: &PlaceElem<'tcx>, - _context: PlaceContext, - location: Location, - ) { - 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(_, _) => { - } - } - } - ); -} - make_mir_visitor!(Visitor,); make_mir_visitor!(MutVisitor,mut); @@ -951,7 +890,7 @@ impl<'tcx> MirVisitable<'tcx> for Option> { /// Extra information passed to `visit_ty` and friends to give context /// about where the type etc appears. -#[derive(Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum TyContext { LocalDecl { /// The index of the local variable we are visiting. diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index fdca6d0e17a1d..4b1558592aee3 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -15,7 +15,7 @@ use crate::traits::query::{ }; use std::borrow::Cow; -use syntax_pos::symbol::Symbol; +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 @@ -61,7 +61,7 @@ rustc_queries! { /// predicate gets in the way of some checks, which are intended /// to operate over only the actual where-clauses written by the /// user.) - query predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { + query predicates_of(key: DefId) -> &'tcx ty::GenericPredicates<'tcx> { cache_on_disk_if { key.is_local() } } @@ -94,7 +94,6 @@ rustc_queries! { /// of the MIR qualify_consts pass. The actual meaning of /// the value isn't known except to the pass itself. query mir_const_qualif(key: DefId) -> (u8, &'tcx BitSet) { - desc { |tcx| "const checking `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } } @@ -133,7 +132,7 @@ rustc_queries! { cache_on_disk_if { key.is_local() } load_cached(tcx, id) { let promoted: Option< - rustc_index::vec::IndexVec< + rustc_data_structures::indexed_vec::IndexVec< crate::mir::Promoted, crate::mir::Body<'tcx> >> = tcx.queries.on_disk_cache.try_load_query_result(tcx, id); @@ -184,10 +183,12 @@ rustc_queries! { /// predicates (where-clauses) directly defined on it. This is /// equal to the `explicit_predicates_of` predicates plus the /// `inferred_outlives_of` predicates. - query predicates_defined_on(_: DefId) -> ty::GenericPredicates<'tcx> {} + query predicates_defined_on(_: DefId) + -> &'tcx ty::GenericPredicates<'tcx> {} /// Returns the predicates written explicitly by the user. - query explicit_predicates_of(_: DefId) -> ty::GenericPredicates<'tcx> {} + query explicit_predicates_of(_: DefId) + -> &'tcx ty::GenericPredicates<'tcx> {} /// Returns the inferred outlives predicates (e.g., for `struct /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). @@ -199,13 +200,14 @@ rustc_queries! { /// evaluate them even during type conversion, often before the /// full predicates are available (note that supertraits have /// additional acyclicity requirements). - query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { + query super_predicates_of(key: DefId) -> &'tcx ty::GenericPredicates<'tcx> { desc { |tcx| "computing the supertraits of `{}`", tcx.def_path_str(key) } } /// To avoid cycles within the predicates of a single item we compute /// per-type-parameter predicates for resolving `T::AssocTy`. - query type_param_predicates(key: (DefId, DefId)) -> ty::GenericPredicates<'tcx> { + query type_param_predicates(key: (DefId, DefId)) + -> &'tcx ty::GenericPredicates<'tcx> { no_force desc { |tcx| "computing the bounds for type parameter `{}`", { let id = tcx.hir().as_local_hir_id(key.1).unwrap(); @@ -228,12 +230,6 @@ rustc_queries! { cycle_delay_bug } - query trivial_dropck_outlives(ty: Ty<'tcx>) -> bool { - anon - no_force - desc { "checking if `{:?}` has trivial dropck", ty } - } - query adt_dtorck_constraint( _: DefId ) -> Result, NoSolution> {} @@ -534,6 +530,19 @@ rustc_queries! { TypeChecking { query trait_of_item(_: DefId) -> Option {} + query const_is_rvalue_promotable_to_static(key: DefId) -> bool { + desc { |tcx| + "const checking if rvalue is promotable to static `{}`", + tcx.def_path_str(key) + } + cache_on_disk_if { true } + } + query rvalue_promotable_map(key: DefId) -> &'tcx ItemLocalSet { + desc { |tcx| + "checking which parts of `{}` are promotable to static", + tcx.def_path_str(key) + } + } } Codegen { @@ -924,7 +933,7 @@ rustc_queries! { desc { "collect_and_partition_mono_items" } } query is_codegened_item(_: DefId) -> bool {} - query codegen_unit(_: Symbol) -> Arc> { + query codegen_unit(_: InternedString) -> Arc> { no_force desc { "codegen_unit" } } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 33b9ddaa62230..7c97fd11af2a5 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -7,16 +7,20 @@ 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 syntax; -use syntax::ast::{self, IntTy, UintTy}; +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::symbol::{sym, Symbol}; use syntax::feature_gate::UnstableFeatures; +use syntax::source_map::SourceMap; use errors::emitter::HumanReadableErrorType; use errors::{ColorConfig, FatalError, Handler}; @@ -62,7 +66,7 @@ impl_stable_hash_via_hash!(OptLevel); /// This is what the `LtoCli` values get mapped to after resolving defaults and /// and taking other command line options into account. -#[derive(Clone, PartialEq)] +#[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum Lto { /// Don't do any LTO whatsoever No, @@ -296,10 +300,10 @@ 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. -#[derive(Clone)] +#[derive(Clone, Hash)] pub struct Externs(BTreeMap); -#[derive(Clone, Debug, Default)] +#[derive(Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug, Default)] pub struct ExternEntry { pub locations: BTreeSet>, pub is_private_dep: bool @@ -459,7 +463,7 @@ pub enum PrintRequest { NativeStaticLibs, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum BorrowckMode { Mir, Migrate, @@ -801,7 +805,6 @@ macro_rules! options { pub const parse_list: Option<&str> = Some("a space-separated list of strings"); pub const parse_opt_list: Option<&str> = Some("a space-separated list of strings"); pub const parse_opt_comma_list: Option<&str> = Some("a comma-separated list of strings"); - pub const parse_threads: Option<&str> = Some("a number"); pub const parse_uint: Option<&str> = Some("a number"); pub const parse_passes: Option<&str> = Some("a space-separated list of passes, or `all`"); @@ -945,14 +948,6 @@ macro_rules! options { } } - fn parse_threads(slot: &mut usize, v: Option<&str>) -> bool { - match v.and_then(|s| s.parse().ok()) { - Some(0) => { *slot = ::num_cpus::get(); true }, - Some(i) => { *slot = i; true }, - None => false - } - } - fn parse_uint(slot: &mut usize, v: Option<&str>) -> bool { match v.and_then(|s| s.parse().ok()) { Some(i) => { *slot = i; true }, @@ -1149,8 +1144,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), target_feature: String = (String::new(), parse_string, [TRACKED], - "target specific attributes. (`rustc --print target-features` for details). \ - This feature is unsafe."), + "target specific attributes (`rustc --print target-features` for details)"), passes: Vec = (Vec::new(), parse_list, [TRACKED], "a list of extra LLVM passes to run (space separated)"), llvm_args: Vec = (Vec::new(), parse_list, [TRACKED], @@ -1257,11 +1251,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "prints the LLVM optimization passes being run"), ast_json: bool = (false, parse_bool, [UNTRACKED], "print the AST as JSON and halt"), - // We default to 1 here since we want to behave like - // a sequential compiler for now. This'll likely be adjusted - // in the future. Note that -Zthreads=0 is the way to get - // the num_cpus behavior. - threads: usize = (1, parse_threads, [UNTRACKED], + threads: Option = (None, parse_opt_uint, [UNTRACKED], "use a thread pool with N threads"), ast_json_noexpand: bool = (false, parse_bool, [UNTRACKED], "print the pre-expansion AST as JSON and halt"), @@ -1289,8 +1279,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "show extended diagnostic help"), terminal_width: Option = (None, parse_opt_uint, [UNTRACKED], "set the current terminal width"), - panic_abort_tests: bool = (false, parse_bool, [TRACKED], - "support compiling tests with panic=abort"), continue_parse_after_error: bool = (false, parse_bool, [TRACKED], "attempt to recover from parse errors (experimental)"), dep_tasks: bool = (false, parse_bool, [UNTRACKED], @@ -1313,6 +1301,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"), query_dep_graph: bool = (false, parse_bool, [UNTRACKED], "enable queries of the dependency graph for regression testing"), + profile_queries: bool = (false, parse_bool, [UNTRACKED], + "trace and profile the queries of the incremental compilation framework"), + profile_queries_and_keys: bool = (false, parse_bool, [UNTRACKED], + "trace and profile the queries and keys of the incremental compilation framework"), no_analysis: bool = (false, parse_bool, [UNTRACKED], "parse and expand the source, but run no analysis"), extra_plugins: Vec = (Vec::new(), parse_list, [TRACKED], @@ -1338,7 +1330,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, mir_opt_level: usize = (1, parse_uint, [TRACKED], "set the MIR optimization level (0-3, default: 1)"), mutable_noalias: Option = (None, parse_opt_bool, [TRACKED], - "emit noalias metadata for mutable references (default: no)"), + "emit noalias metadata for mutable references (default: yes on LLVM >= 6)"), dump_mir: Option = (None, parse_opt_string, [UNTRACKED], "dump MIR state to file. `val` is used to select which passes and functions to dump. For example: @@ -1464,9 +1456,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "which mangling version to use for symbol names"), binary_dep_depinfo: bool = (false, parse_bool, [TRACKED], "include artifacts (sysroot, crate dependencies) used during compilation in dep-info"), - insert_sideeffect: bool = (false, parse_bool, [TRACKED], - "fix undefined behavior when a thread doesn't eventually make progress \ - (such as entering an empty infinite loop) by inserting llvm.sideeffect"), } pub fn default_lib_output() -> CrateType { @@ -1510,25 +1499,22 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { } for &i in &[8, 16, 32, 64, 128] { if i >= min_atomic_width && i <= max_atomic_width { - let mut insert_atomic = |s| { - ret.insert(( - sym::target_has_atomic_load_store, - Some(Symbol::intern(s)), - )); - if atomic_cas { - ret.insert(( - sym::target_has_atomic, - Some(Symbol::intern(s)) - )); - } - }; let s = i.to_string(); - insert_atomic(&s); + ret.insert(( + sym::target_has_atomic, + Some(Symbol::intern(&s)), + )); if &s == wordsz { - insert_atomic("ptr"); + ret.insert(( + sym::target_has_atomic, + Some(Symbol::intern("ptr")), + )); } } } + if atomic_cas { + ret.insert((sym::target_has_atomic, Some(Symbol::intern("cas")))); + } if sess.opts.debug_assertions { ret.insert((Symbol::intern("debug_assertions"), None)); } @@ -1850,6 +1836,58 @@ pub fn rustc_optgroups() -> Vec { opts } +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 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 = new_parser_from_source_str(&sess, filename, s.to_string()); + + macro_rules! error {($reason: expr) => { + early_error(ErrorOutputType::default(), + &format!(concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s)); + }} + + match &mut parser.parse_meta_item() { + Ok(meta_item) if parser.token == token::Eof => { + if meta_item.path.segments.len() != 1 { + error!("argument key must be an identifier"); + } + match &meta_item.kind { + MetaItemKind::List(..) => { + error!(r#"expected `key` or `key="value"`"#); + } + MetaItemKind::NameValue(lit) if !lit.kind.is_str() => { + error!("argument value must be a string"); + } + MetaItemKind::NameValue(..) | MetaItemKind::Word => { + let ident = meta_item.ident().expect("multi-segment cfg key"); + return (ident.name, meta_item.value_str()); + } + } + } + Ok(..) => {} + Err(err) => err.cancel(), + } + + error!(r#"expected `key` or `key="value"`"#); + }).collect::(); + cfg.into_iter().map(|(a, b)| { + (a.to_string(), b.map(|b| b.to_string())) + }).collect() + }) +} + pub fn get_cmd_lint_options(matches: &getopts::Matches, error_format: ErrorOutputType) -> (Vec<(String, lint::Level)>, bool, Option) { @@ -1983,7 +2021,11 @@ pub fn parse_error_format( return error_format; } -fn parse_crate_edition(matches: &getopts::Matches) -> Edition { +pub fn build_session_options_and_crate_config( + matches: &getopts::Matches, +) -> (Options, FxHashSet<(String, Option)>) { + let color = parse_color(matches); + let edition = match matches.opt_str("edition") { Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| early_error( @@ -2010,14 +2052,19 @@ fn parse_crate_edition(matches: &getopts::Matches) -> Edition { ) } - edition -} + let (json_rendered, json_artifact_notifications) = parse_json(matches); + + let error_format = parse_error_format(matches, color, json_rendered); + + let unparsed_crate_types = matches.opt_strs("crate-type"); + let crate_types = parse_crate_types_from_list(unparsed_crate_types) + .unwrap_or_else(|e| early_error(error_format, &e[..])); + + + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); + + let mut debugging_opts = build_debugging_options(matches, error_format); -fn check_debug_option_stability( - debugging_opts: &DebuggingOptions, - error_format: ErrorOutputType, - json_rendered: HumanReadableErrorType, -) { if !debugging_opts.unstable_options { if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format { early_error( @@ -2033,13 +2080,7 @@ fn check_debug_option_stability( ); } } -} -fn parse_output_types( - debugging_opts: &DebuggingOptions, - matches: &getopts::Matches, - error_format: ErrorOutputType, -) -> OutputTypes { let mut output_types = BTreeMap::new(); if !debugging_opts.parse_only { for list in matches.opt_strs("emit") { @@ -2064,19 +2105,14 @@ fn parse_output_types( if output_types.is_empty() { output_types.insert(OutputType::Exe, None); } - OutputTypes(output_types) -} -fn should_override_cgus_and_disable_thinlto( - output_types: &OutputTypes, - matches: &getopts::Matches, - error_format: ErrorOutputType, - mut codegen_units: Option, -) -> (bool, Option) { + let mut cg = build_codegen_options(matches, error_format); + let mut codegen_units = cg.codegen_units; let mut disable_thinlto = false; + // Issue #30063: if user requests LLVM-related output to one // particular path, disable codegen-units. - let incompatible: Vec<_> = output_types.0 + let incompatible: Vec<_> = output_types .iter() .map(|ot_path| ot_path.0) .filter(|ot| !ot.is_compatible_with_codegen_units_and_single_output_file()) @@ -2108,39 +2144,29 @@ fn should_override_cgus_and_disable_thinlto( } } - if codegen_units == Some(0) { + if debugging_opts.threads == Some(0) { early_error( error_format, - "value for codegen units must be a positive non-zero integer", + "value for threads must be a positive non-zero integer", ); } - (disable_thinlto, codegen_units) -} - -fn check_thread_count(debugging_opts: &DebuggingOptions, error_format: ErrorOutputType) { - if debugging_opts.threads == 0 { + if debugging_opts.threads.unwrap_or(1) > 1 && debugging_opts.fuel.is_some() { early_error( error_format, - "value for threads must be a positive non-zero integer", + "optimization fuel is incompatible with multiple threads", ); } - if debugging_opts.threads > 1 && debugging_opts.fuel.is_some() { + if codegen_units == Some(0) { early_error( error_format, - "optimization fuel is incompatible with multiple threads", + "value for codegen units must be a positive non-zero integer", ); } -} -fn select_incremental_path( - debugging_opts: &DebuggingOptions, - cg: &CodegenOptions, - error_format: ErrorOutputType, -) -> Option { - match (&debugging_opts.incremental, &cg.incremental) { - (Some(path1), Some(path2)) => { + let incremental = match (&debugging_opts.incremental, &cg.incremental) { + (&Some(ref path1), &Some(ref path2)) => { if path1 != path2 { early_error( error_format, @@ -2154,19 +2180,25 @@ fn select_incremental_path( Some(path1) } } - (Some(path), None) => Some(path), - (None, Some(path)) => Some(path), - (None, None) => None, - }.map(|m| PathBuf::from(m)) -} + (&Some(ref path), &None) => Some(path), + (&None, &Some(ref path)) => Some(path), + (&None, &None) => None, + }.map(|m| PathBuf::from(m)); + + if debugging_opts.profile && incremental.is_some() { + early_error( + error_format, + "can't instrument with gcov profiling when compiling incrementally", + ); + } + + if cg.profile_generate.enabled() && cg.profile_use.is_some() { + early_error( + error_format, + "options `-C profile-generate` and `-C profile-use` are exclusive", + ); + } -fn collect_print_requests( - cg: &mut CodegenOptions, - dopts: &mut DebuggingOptions, - matches: &getopts::Matches, - is_unstable_enabled: bool, - error_format: ErrorOutputType, -) -> Vec { let mut prints = Vec::::new(); if cg.target_cpu.as_ref().map_or(false, |s| s == "help") { prints.push(PrintRequest::TargetCPUs); @@ -2184,105 +2216,72 @@ fn collect_print_requests( prints.push(PrintRequest::CodeModels); cg.code_model = None; } - if dopts + if debugging_opts .tls_model .as_ref() .map_or(false, |s| s == "help") { prints.push(PrintRequest::TlsModels); - dopts.tls_model = None; + debugging_opts.tls_model = None; } - prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s { - "crate-name" => PrintRequest::CrateName, - "file-names" => PrintRequest::FileNames, - "sysroot" => PrintRequest::Sysroot, - "cfg" => PrintRequest::Cfg, - "target-list" => PrintRequest::TargetList, - "target-cpus" => PrintRequest::TargetCPUs, - "target-features" => PrintRequest::TargetFeatures, - "relocation-models" => PrintRequest::RelocationModels, - "code-models" => PrintRequest::CodeModels, - "tls-models" => PrintRequest::TlsModels, - "native-static-libs" => PrintRequest::NativeStaticLibs, - "target-spec-json" => { - if is_unstable_enabled { - PrintRequest::TargetSpec - } else { - early_error( - error_format, - "the `-Z unstable-options` flag must also be passed to \ - enable the target-spec-json print option", - ); - } - } - req => early_error(error_format, &format!("unknown print request `{}`", req)), - })); - - prints -} + let cg = cg; -fn parse_target_triple(matches: &getopts::Matches, error_format: ErrorOutputType) -> TargetTriple { - match matches.opt_str("target") { - Some(target) if target.ends_with(".json") => { + let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); + let target_triple = if let Some(target) = matches.opt_str("target") { + if target.ends_with(".json") { let path = Path::new(&target); TargetTriple::from_path(&path).unwrap_or_else(|_| early_error(error_format, &format!("target file {:?} does not exist", path))) - } - Some(target) => TargetTriple::TargetTriple(target), - _ => TargetTriple::from_triple(host_triple()), - } -} - -fn parse_opt_level( - matches: &getopts::Matches, - cg: &CodegenOptions, - error_format: ErrorOutputType, -) -> OptLevel { - // The `-O` and `-C opt-level` flags specify the same setting, so we want to be able - // to use them interchangeably. However, because they're technically different flags, - // we need to work out manually which should take precedence if both are supplied (i.e. - // the rightmost flag). We do this by finding the (rightmost) position of both flags and - // comparing them. Note that if a flag is not found, its position will be `None`, which - // always compared less than `Some(_)`. - let max_o = matches.opt_positions("O").into_iter().max(); - let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| { - if let Some("opt-level") = s.splitn(2, '=').next() { - Some(i) } else { - None + TargetTriple::TargetTriple(target) } - }).max(); - if max_o > max_c { - OptLevel::Default } else { - match cg.opt_level.as_ref().map(String::as_ref) { - None => OptLevel::No, - Some("0") => OptLevel::No, - Some("1") => OptLevel::Less, - Some("2") => OptLevel::Default, - Some("3") => OptLevel::Aggressive, - Some("s") => OptLevel::Size, - Some("z") => OptLevel::SizeMin, - Some(arg) => { - early_error( - error_format, - &format!( - "optimization level needs to be \ - between 0-3, s or z (instead was `{}`)", - arg - ), - ); + TargetTriple::from_triple(host_triple()) + }; + let opt_level = { + // The `-O` and `-C opt-level` flags specify the same setting, so we want to be able + // to use them interchangeably. However, because they're technically different flags, + // we need to work out manually which should take precedence if both are supplied (i.e. + // the rightmost flag). We do this by finding the (rightmost) position of both flags and + // comparing them. Note that if a flag is not found, its position will be `None`, which + // always compared less than `Some(_)`. + let max_o = matches.opt_positions("O").into_iter().max(); + let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| { + if let Some("opt-level") = s.splitn(2, '=').next() { + Some(i) + } else { + None + } + }).max(); + if max_o > max_c { + OptLevel::Default + } else { + match cg.opt_level.as_ref().map(String::as_ref) { + None => OptLevel::No, + Some("0") => OptLevel::No, + Some("1") => OptLevel::Less, + Some("2") => OptLevel::Default, + Some("3") => OptLevel::Aggressive, + Some("s") => OptLevel::Size, + Some("z") => OptLevel::SizeMin, + Some(arg) => { + early_error( + error_format, + &format!( + "optimization level needs to be \ + between 0-3, s or z (instead was `{}`)", + arg + ), + ); + } } } - } -} - -fn select_debuginfo( - matches: &getopts::Matches, - cg: &CodegenOptions, - error_format: ErrorOutputType, -) -> DebugInfo { + }; + // The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able + // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`) + // for more details. + let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); let max_g = matches.opt_positions("g").into_iter().max(); let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| { if let Some("debuginfo") = s.splitn(2, '=').next() { @@ -2291,7 +2290,7 @@ fn select_debuginfo( None } }).max(); - if max_g > max_c { + let debuginfo = if max_g > max_c { DebugInfo::Full } else { match cg.debuginfo { @@ -2309,14 +2308,14 @@ fn select_debuginfo( ); } } + }; + + let mut search_paths = vec![]; + for s in &matches.opt_strs("L") { + search_paths.push(SearchPath::from_cli_opt(&s[..], error_format)); } -} -fn parse_libs( - matches: &getopts::Matches, - error_format: ErrorOutputType, -) -> Vec<(String, Option, Option)> { - matches + let libs = matches .opt_strs("l") .into_iter() .map(|s| { @@ -2355,23 +2354,52 @@ fn parse_libs( let new_name = name_parts.next(); (name.to_owned(), new_name.map(|n| n.to_owned()), kind) }) - .collect() -} + .collect(); -fn parse_borrowck_mode(dopts: &DebuggingOptions, error_format: ErrorOutputType) -> BorrowckMode { - match dopts.borrowck.as_ref().map(|s| &s[..]) { + let cfg = parse_cfgspecs(matches.opt_strs("cfg")); + let test = matches.opt_present("test"); + + let is_unstable_enabled = nightly_options::is_unstable_enabled(matches); + + prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s { + "crate-name" => PrintRequest::CrateName, + "file-names" => PrintRequest::FileNames, + "sysroot" => PrintRequest::Sysroot, + "cfg" => PrintRequest::Cfg, + "target-list" => PrintRequest::TargetList, + "target-cpus" => PrintRequest::TargetCPUs, + "target-features" => PrintRequest::TargetFeatures, + "relocation-models" => PrintRequest::RelocationModels, + "code-models" => PrintRequest::CodeModels, + "tls-models" => PrintRequest::TlsModels, + "native-static-libs" => PrintRequest::NativeStaticLibs, + "target-spec-json" => { + if is_unstable_enabled { + PrintRequest::TargetSpec + } else { + early_error( + error_format, + "the `-Z unstable-options` flag must also be passed to \ + enable the target-spec-json print option", + ); + } + } + req => early_error(error_format, &format!("unknown print request `{}`", req)), + })); + + let borrowck_mode = match debugging_opts.borrowck.as_ref().map(|s| &s[..]) { None | Some("migrate") => BorrowckMode::Migrate, Some("mir") => BorrowckMode::Mir, Some(m) => early_error(error_format, &format!("unknown borrowck mode `{}`", m)), + }; + + if !cg.remark.is_empty() && debuginfo == DebugInfo::None { + early_warn( + error_format, + "-C remark requires \"-C debuginfo=n\" to show source locations", + ); } -} -fn parse_externs( - matches: &getopts::Matches, - debugging_opts: &DebuggingOptions, - error_format: ErrorOutputType, - is_unstable_enabled: bool, -) -> Externs { if matches.opt_present("extern-private") && !debugging_opts.unstable_options { early_error( ErrorOutputType::default(), @@ -2412,14 +2440,10 @@ fn parse_externs( // flag entry.is_private_dep |= private; } - Externs(externs) -} -fn parse_remap_path_prefix( - matches: &getopts::Matches, - error_format: ErrorOutputType -) -> Vec<(PathBuf, PathBuf)> { - matches + let crate_name = matches.opt_str("crate-name"); + + let remap_path_prefix = matches .opt_strs("remap-path-prefix") .into_iter() .map(|remap| { @@ -2434,130 +2458,42 @@ fn parse_remap_path_prefix( ), } }) - .collect() -} - -pub fn build_session_options(matches: &getopts::Matches) -> Options { - let color = parse_color(matches); - - let edition = parse_crate_edition(matches); - - let (json_rendered, json_artifact_notifications) = parse_json(matches); - - let error_format = parse_error_format(matches, color, json_rendered); - - let unparsed_crate_types = matches.opt_strs("crate-type"); - let crate_types = parse_crate_types_from_list(unparsed_crate_types) - .unwrap_or_else(|e| early_error(error_format, &e[..])); - - let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); - - let mut debugging_opts = build_debugging_options(matches, error_format); - check_debug_option_stability(&debugging_opts, error_format, json_rendered); - - let output_types = parse_output_types(&debugging_opts, matches, error_format); - - let mut cg = build_codegen_options(matches, error_format); - let (disable_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto( - &output_types, - matches, - error_format, - cg.codegen_units, - ); - - check_thread_count(&debugging_opts, error_format); - - let incremental = select_incremental_path(&debugging_opts, &cg, error_format); - - if debugging_opts.profile && incremental.is_some() { - early_error( - error_format, - "can't instrument with gcov profiling when compiling incrementally", - ); - } - - if cg.profile_generate.enabled() && cg.profile_use.is_some() { - early_error( - error_format, - "options `-C profile-generate` and `-C profile-use` are exclusive", - ); - } - - let is_unstable_enabled = nightly_options::is_unstable_enabled(matches); - let prints = collect_print_requests( - &mut cg, - &mut debugging_opts, - matches, - is_unstable_enabled, - error_format, - ); - - let cg = cg; - - let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); - let target_triple = parse_target_triple(matches, error_format); - let opt_level = parse_opt_level(matches, &cg, error_format); - // The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able - // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`) - // for more details. - let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); - let debuginfo = select_debuginfo(matches, &cg, error_format); - - let mut search_paths = vec![]; - for s in &matches.opt_strs("L") { - search_paths.push(SearchPath::from_cli_opt(&s[..], error_format)); - } - - let libs = parse_libs(matches, error_format); - - let test = matches.opt_present("test"); - - let borrowck_mode = parse_borrowck_mode(&debugging_opts, error_format); + .collect(); - if !cg.remark.is_empty() && debuginfo == DebugInfo::None { - early_warn( + ( + Options { + crate_types, + optimize: opt_level, + debuginfo, + lint_opts, + lint_cap, + describe_lints, + output_types: OutputTypes(output_types), + search_paths, + maybe_sysroot: sysroot_opt, + target_triple, + test, + incremental, + debugging_opts, + prints, + borrowck_mode, + cg, error_format, - "-C remark requires \"-C debuginfo=n\" to show source locations", - ); - } - - let externs = parse_externs(matches, &debugging_opts, error_format, is_unstable_enabled); - - let crate_name = matches.opt_str("crate-name"); - - let remap_path_prefix = parse_remap_path_prefix(matches, error_format); - - Options { - crate_types, - optimize: opt_level, - debuginfo, - lint_opts, - lint_cap, - describe_lints, - output_types, - search_paths, - maybe_sysroot: sysroot_opt, - target_triple, - test, - incremental, - debugging_opts, - prints, - borrowck_mode, - cg, - error_format, - externs, - crate_name, - alt_std_name: None, - libs, - unstable_features: UnstableFeatures::from_environment(), - debug_assertions, - actually_rustdoc: false, - cli_forced_codegen_units: codegen_units, - cli_forced_thinlto_off: disable_thinlto, - remap_path_prefix, - edition, - json_artifact_notifications, - } + externs: Externs(externs), + crate_name, + alt_std_name: None, + libs, + unstable_features: UnstableFeatures::from_environment(), + debug_assertions, + actually_rustdoc: false, + cli_forced_codegen_units: codegen_units, + cli_forced_thinlto_off: disable_thinlto, + remap_path_prefix, + edition, + json_artifact_notifications, + }, + cfg, + ) } pub fn make_crate_type_option() -> RustcOptGroup { @@ -2820,3 +2756,6 @@ mod dep_tracking { } } } + +#[cfg(test)] +mod tests; diff --git a/src/librustc_interface/tests.rs b/src/librustc/session/config/tests.rs similarity index 92% rename from src/librustc_interface/tests.rs rename to src/librustc/session/config/tests.rs index 7a57605da58b8..c117418f63699 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc/session/config/tests.rs @@ -1,51 +1,40 @@ -extern crate getopts; - -use crate::interface::parse_cfgspecs; - -use rustc::lint; -use rustc::middle::cstore; -use rustc::session::config::{build_configuration, build_session_options, to_crate_config}; -use rustc::session::config::{LtoCli, LinkerPluginLto, SwitchWithOptPath, ExternEntry}; -use rustc::session::config::{Externs, OutputType, OutputTypes, SymbolManglingVersion}; -use rustc::session::config::{rustc_optgroups, Options, ErrorOutputType, Passes}; -use rustc::session::build_session; -use rustc::session::search_paths::SearchPath; +use getopts; +use crate::lint; +use crate::middle::cstore; +use crate::session::config::{ + build_configuration, + build_session_options_and_crate_config, + to_crate_config +}; +use crate::session::config::{LtoCli, LinkerPluginLto, SwitchWithOptPath, ExternEntry}; +use crate::session::build_session; +use crate::session::search_paths::SearchPath; use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; use std::path::PathBuf; +use super::{Externs, OutputType, OutputTypes, SymbolManglingVersion}; use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel}; use syntax::symbol::sym; use syntax::edition::{Edition, DEFAULT_EDITION}; use syntax; -use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{ColorConfig, emitter::HumanReadableErrorType, registry}; - -pub fn build_session_options_and_crate_config( - matches: &getopts::Matches, -) -> (Options, FxHashSet<(String, Option)>) { - ( - build_session_options(matches), - parse_cfgspecs(matches.opt_strs("cfg")), - ) -} - -fn new_public_extern_entry(locations: I) -> ExternEntry -where - S: Into, - I: IntoIterator>, -{ - let locations: BTreeSet<_> = locations.into_iter().map(|o| o.map(|s| s.into())) - .collect(); - - ExternEntry { - locations, - is_private_dep: false +use super::Options; + +impl ExternEntry { + fn new_public, + I: IntoIterator>>(locations: I) -> ExternEntry { + let locations: BTreeSet<_> = locations.into_iter().map(|o| o.map(|s| s.into())) + .collect(); + + ExternEntry { + locations, + is_private_dep: false + } } } fn optgroups() -> getopts::Options { let mut opts = getopts::Options::new(); - for group in rustc_optgroups() { + for group in super::rustc_optgroups() { (group.apply)(&mut opts); } return opts; @@ -63,7 +52,7 @@ fn test_switch_implies_cfg_test() { Ok(m) => m, Err(f) => panic!("test_switch_implies_cfg_test: {}", f), }; - let registry = registry::Registry::new(&[]); + let registry = errors::registry::Registry::new(&[]); let (sessopts, cfg) = build_session_options_and_crate_config(matches); let sess = build_session(sessopts, None, registry); let cfg = build_configuration(&sess, to_crate_config(cfg)); @@ -81,7 +70,7 @@ fn test_switch_implies_cfg_test_unless_cfg_test() { Ok(m) => m, Err(f) => panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f), }; - let registry = registry::Registry::new(&[]); + let registry = errors::registry::Registry::new(&[]); let (sessopts, cfg) = build_session_options_and_crate_config(matches); let sess = build_session(sessopts, None, registry); let cfg = build_configuration(&sess, to_crate_config(cfg)); @@ -95,7 +84,7 @@ fn test_switch_implies_cfg_test_unless_cfg_test() { fn test_can_print_warnings() { syntax::with_default_globals(|| { let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap(); - let registry = registry::Registry::new(&[]); + 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().can_emit_warnings()); @@ -105,7 +94,7 @@ fn test_can_print_warnings() { let matches = optgroups() .parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]) .unwrap(); - let registry = registry::Registry::new(&[]); + 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().can_emit_warnings()); @@ -113,7 +102,7 @@ fn test_can_print_warnings() { syntax::with_default_globals(|| { let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap(); - let registry = registry::Registry::new(&[]); + 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().can_emit_warnings()); @@ -172,33 +161,33 @@ fn test_externs_tracking_hash_different_construction_order() { v1.externs = Externs::new(mk_map(vec![ ( String::from("a"), - new_public_extern_entry(vec![Some("b"), Some("c")]) + ExternEntry::new_public(vec![Some("b"), Some("c")]) ), ( String::from("d"), - new_public_extern_entry(vec![Some("e"), Some("f")]) + ExternEntry::new_public(vec![Some("e"), Some("f")]) ), ])); v2.externs = Externs::new(mk_map(vec![ ( String::from("d"), - new_public_extern_entry(vec![Some("e"), Some("f")]) + ExternEntry::new_public(vec![Some("e"), Some("f")]) ), ( String::from("a"), - new_public_extern_entry(vec![Some("b"), Some("c")]) + ExternEntry::new_public(vec![Some("b"), Some("c")]) ), ])); v3.externs = Externs::new(mk_map(vec![ ( String::from("a"), - new_public_extern_entry(vec![Some("b"), Some("c")]) + ExternEntry::new_public(vec![Some("b"), Some("c")]) ), ( String::from("d"), - new_public_extern_entry(vec![Some("f"), Some("e")]) + ExternEntry::new_public(vec![Some("f"), Some("e")]) ), ])); @@ -282,9 +271,9 @@ fn test_search_paths_tracking_hash_different_order() { let mut v3 = Options::default(); let mut v4 = Options::default(); - const JSON: ErrorOutputType = ErrorOutputType::Json { + const JSON: super::ErrorOutputType = super::ErrorOutputType::Json { pretty: false, - json_rendered: HumanReadableErrorType::Default(ColorConfig::Never), + json_rendered: super::HumanReadableErrorType::Default(super::ColorConfig::Never), }; // Reference @@ -455,7 +444,7 @@ fn test_codegen_options_tracking_hash() { opts.cg.codegen_units = Some(42); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.cg.remark = Passes::Some(vec![String::from("pass1"), String::from("pass2")]); + opts.cg.remark = super::Passes::Some(vec![String::from("pass1"), String::from("pass2")]); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.cg.save_temps = true; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index bd2460cfab116..8e9c2735c3913 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -7,14 +7,15 @@ use rustc_data_structures::fingerprint::Fingerprint; use crate::lint; use crate::lint::builtin::BuiltinLintDiagnostics; -use crate::session::config::{OutputType, PrintRequest, Sanitizer, SwitchWithOptPath}; +use crate::session::config::{OutputType, PrintRequest, SwitchWithOptPath}; use crate::session::search_paths::{PathKind, SearchPath}; use crate::util::nodemap::{FxHashMap, FxHashSet}; use crate::util::common::{duration_to_secs_str, ErrorReported}; +use crate::util::common::ProfileQueriesMsg; use rustc_data_structures::base_n; use rustc_data_structures::sync::{ - self, Lrc, Lock, OneThread, Once, AtomicU64, AtomicUsize, Ordering, + self, Lrc, Lock, OneThread, Once, RwLock, AtomicU64, AtomicUsize, Ordering, Ordering::SeqCst, }; @@ -24,14 +25,14 @@ use errors::emitter::HumanReadableErrorType; use errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter}; use syntax::ast::{self, NodeId}; use syntax::edition::Edition; -use syntax_expand::allocator::AllocatorKind; +use syntax::ext::allocator::AllocatorKind; use syntax::feature_gate::{self, AttributeType}; use syntax::json::JsonEmitter; use syntax::source_map; -use syntax::sess::ParseSess; +use syntax::parse::{self, ParseSess}; use syntax::symbol::Symbol; use syntax_pos::{MultiSpan, Span}; -use crate::util::profiling::{SelfProfiler, SelfProfilerRef}; +use crate::util::profiling::SelfProfiler; use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple}; use rustc_data_structures::flock; @@ -45,7 +46,7 @@ use std::fmt; use std::io::Write; use std::path::PathBuf; use std::time::Duration; -use std::sync::Arc; +use std::sync::{Arc, mpsc}; mod code_stats; pub mod config; @@ -77,11 +78,9 @@ pub struct Session { /// if the value stored here has been affected by path remapping. pub working_dir: (PathBuf, bool), - /// This is intended to be used from a single thread. - /// - /// FIXME: there was a previous comment about this not being thread safe, - /// but it's not clear how or why that's the case. The LintBuffer itself is certainly thread - /// safe at least from a "Rust safety" standpoint. + // 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 @@ -126,8 +125,11 @@ pub struct Session { /// `-Zquery-dep-graph` is specified. pub cgu_reuse_tracker: CguReuseTracker, + /// Used by `-Z profile-queries` in `util::common`. + pub profile_channel: Lock>>, + /// Used by `-Z self-profile`. - pub prof: SelfProfilerRef, + pub self_profiling: Option>, /// Some measurements that are being gathered during compilation. pub perf_stats: PerfStats, @@ -507,6 +509,13 @@ impl Session { pub fn time_extended(&self) -> bool { self.opts.debugging_opts.time_passes } + pub fn profile_queries(&self) -> bool { + self.opts.debugging_opts.profile_queries + || self.opts.debugging_opts.profile_queries_and_keys + } + pub fn profile_queries_and_keys(&self) -> bool { + self.opts.debugging_opts.profile_queries_and_keys + } pub fn instrument_mcount(&self) -> bool { self.opts.debugging_opts.instrument_mcount } @@ -628,14 +637,6 @@ impl Session { .output_types .contains_key(&OutputType::LlvmAssembly) || self.opts.output_types.contains_key(&OutputType::Bitcode); - - // Address sanitizer and memory sanitizer use alloca name when reporting an issue. - let more_names = match self.opts.debugging_opts.sanitizer { - Some(Sanitizer::Address) => true, - Some(Sanitizer::Memory) => true, - _ => more_names, - }; - self.opts.debugging_opts.fewer_names || !more_names } @@ -834,6 +835,24 @@ impl Session { } } + #[inline(never)] + #[cold] + fn profiler_active ()>(&self, f: F) { + match &self.self_profiling { + None => bug!("profiler_active() called but there was no profiler active"), + Some(profiler) => { + f(&profiler); + } + } + } + + #[inline(always)] + pub fn profiler ()>(&self, f: F) { + if unlikely!(self.self_profiling.is_some()) { + self.profiler_active(f) + } + } + pub fn print_perf_stats(&self) { println!( "Total time spent computing symbol hashes: {}", @@ -877,10 +896,16 @@ impl Session { ret } + /// Returns the number of query threads that should be used for this + /// compilation + pub fn threads_from_count(query_threads: Option) -> usize { + query_threads.unwrap_or(::num_cpus::get()) + } + /// Returns the number of query threads that should be used for this /// compilation pub fn threads(&self) -> usize { - self.opts.debugging_opts.threads + Self::threads_from_count(self.opts.debugging_opts.threads) } /// Returns the number of codegen units that should be used for this @@ -1161,7 +1186,7 @@ fn build_session_( ); let target_cfg = config::build_target_config(&sopts, &span_diagnostic); - let parse_sess = ParseSess::with_span_handler( + let parse_sess = parse::ParseSess::with_span_handler( span_diagnostic, source_map, ); @@ -1215,6 +1240,7 @@ fn build_session_( sysroot, local_crate_source_file, working_dir, + lint_store: RwLock::new(lint::LintStore::new()), buffered_lints: Lock::new(Some(Default::default())), one_time_diagnostics: Default::default(), plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())), @@ -1231,7 +1257,8 @@ fn build_session_( imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), cgu_reuse_tracker, - prof: SelfProfilerRef::new(self_profiler), + self_profiling: self_profiler, + profile_channel: Lock::new(None), perf_stats: PerfStats { symbol_hash_time: Lock::new(Duration::from_secs(0)), decode_def_path_tables_time: Lock::new(Duration::from_secs(0)), diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs index 949dad751a101..3695f0a82f4b0 100644 --- a/src/librustc/session/search_paths.rs +++ b/src/librustc/session/search_paths.rs @@ -1,4 +1,5 @@ use std::path::{Path, PathBuf}; +use rustc_macros::HashStable; use crate::session::{early_error, config}; use crate::session::filesearch::make_target_lib_path; @@ -9,7 +10,7 @@ pub struct SearchPath { pub files: Vec, } -#[derive(PartialEq, Clone, Copy, Debug, HashStable)] +#[derive(Eq, PartialEq, Clone, Copy, Debug, PartialOrd, Ord, Hash, HashStable)] pub enum PathKind { Native, Crate, diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 4696d4da58ec0..039973d80dbf1 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -378,15 +378,7 @@ fn orphan_check_trait_ref<'tcx>( // Let Ti be the first such type. // - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti) // - fn uncover_fundamental_ty(ty: Ty<'_>) -> Vec> { - if fundamental_ty(ty) { - ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(ty)).collect() - } else { - vec![ty] - } - } - - for input_ty in trait_ref.input_types().flat_map(uncover_fundamental_ty) { + for input_ty in trait_ref.input_types() { debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty); if ty_is_local(tcx, input_ty, in_crate) { debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index e684cdc0a3872..c2d531793372a 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -24,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, DefIdTree, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use crate::ty::GenericParamDefKind; use crate::ty::error::ExpectedFound; use crate::ty::fast_reject; @@ -37,7 +37,7 @@ use errors::{Applicability, DiagnosticBuilder, pluralise}; use std::fmt; use syntax::ast; use syntax::symbol::{sym, kw}; -use syntax_pos::{DUMMY_SP, Span, ExpnKind, MultiSpan}; +use syntax_pos::{DUMMY_SP, Span, ExpnKind}; impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn report_fulfillment_errors( @@ -406,7 +406,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }, GenericParamDefKind::Lifetime => continue, }; - let name = param.name; + let name = param.name.as_symbol(); flags.push((name, Some(value))); } @@ -453,17 +453,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - fn find_similar_impl_candidates( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - ) -> Vec> { - let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true); + fn find_similar_impl_candidates(&self, + trait_ref: ty::PolyTraitRef<'tcx>) + -> Vec> + { + let simp = fast_reject::simplify_type(self.tcx, + trait_ref.skip_binder().self_ty(), + true); let all_impls = self.tcx.all_impls(trait_ref.def_id()); match simp { Some(simp) => all_impls.iter().filter_map(|&def_id| { let imp = self.tcx.impl_trait_ref(def_id).unwrap(); - let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); + let imp_simp = fast_reject::simplify_type(self.tcx, + imp.self_ty(), + true); if let Some(imp_simp) = imp_simp { if simp != imp_simp { return None @@ -478,11 +482,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - fn report_similar_impl_candidates( - &self, - impl_candidates: Vec>, - err: &mut DiagnosticBuilder<'_>, - ) { + fn report_similar_impl_candidates(&self, + impl_candidates: Vec>, + err: &mut DiagnosticBuilder<'_>) + { if impl_candidates.is_empty() { return; } @@ -547,8 +550,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.suggest_new_overflow_limit(&mut err); } - self.note_obligation_cause_code(&mut err, &obligation.predicate, &obligation.cause.code, - &mut vec![]); + self.note_obligation_cause(&mut err, obligation); err.emit(); self.tcx.sess.abort_if_errors(); @@ -715,23 +717,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // these notes will often be of the form // "the type `T` can't be frobnicated" // which is somewhat confusing. - self.suggest_restricting_param_bound( - &mut err, - &trait_ref, - obligation.cause.body_id, - ); - } else { - if !have_alt_message { - // Can't show anything else useful, try to find similar impls. - let impl_candidates = self.find_similar_impl_candidates(trait_ref); - self.report_similar_impl_candidates(impl_candidates, &mut err); - } - self.suggest_change_mut( - &obligation, - &mut err, - &trait_ref, - points_at_arg, - ); + err.help(&format!("consider adding a `where {}` bound", + trait_ref.to_predicate())); + } else if !have_alt_message { + // Can't show anything else useful, try to find similar impls. + let impl_candidates = self.find_similar_impl_candidates(trait_ref); + self.report_similar_impl_candidates(impl_candidates, &mut err); } // If this error is due to `!: Trait` not implemented but `(): Trait` is @@ -793,11 +784,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty::Predicate::ObjectSafe(trait_def_id) => { let violations = self.tcx.object_safety_violations(trait_def_id); - self.tcx.report_object_safety_error( + if let Some(err) = self.tcx.report_object_safety_error( span, trait_def_id, violations, - ) + ) { + err + } else { + return; + } } ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { @@ -890,14 +885,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.hir().span_if_local(did) ).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def - if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) { - // We check closures twice, with obligations flowing in different directions, - // but we want to complain about them only once. - return; - } - - self.reported_closure_mismatch.borrow_mut().insert((span, found_span)); - let found = match found_trait_ref.skip_binder().substs.type_at(1).kind { ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()], _ => vec![ArgKind::empty()], @@ -933,7 +920,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { TraitNotObjectSafe(did) => { let violations = self.tcx.object_safety_violations(did); - self.tcx.report_object_safety_error(span, did, violations) + if let Some(err) = self.tcx.report_object_safety_error(span, did, violations) { + err + } else { + return; + } } // already reported in the query @@ -949,181 +940,10 @@ 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(); } - fn suggest_restricting_param_bound( - &self, - err: &mut DiagnosticBuilder<'_>, - trait_ref: &ty::PolyTraitRef<'_>, - body_id: hir::HirId, - ) { - let self_ty = trait_ref.self_ty(); - let (param_ty, projection) = match &self_ty.kind { - ty::Param(_) => (true, None), - ty::Projection(projection) => (false, Some(projection)), - _ => return, - }; - - let mut suggest_restriction = |generics: &hir::Generics, msg| { - let span = generics.where_clause.span_for_predicates_or_empty_place(); - if !span.from_expansion() && span.desugaring_kind().is_none() { - err.span_suggestion( - generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(), - &format!("consider further restricting {}", msg), - format!( - "{} {} ", - if !generics.where_clause.predicates.is_empty() { - "," - } else { - " where" - }, - trait_ref.to_predicate(), - ), - Applicability::MachineApplicable, - ); - } - }; - - // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we - // don't suggest `T: Sized + ?Sized`. - let mut hir_id = body_id; - while let Some(node) = self.tcx.hir().find(hir_id) { - match node { - hir::Node::TraitItem(hir::TraitItem { - generics, - kind: hir::TraitItemKind::Method(..), .. - }) if param_ty && self_ty == self.tcx.types.self_param => { - // Restricting `Self` for a single method. - suggest_restriction(&generics, "`Self`"); - return; - } - - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(_, _, generics, _), .. - }) | - hir::Node::TraitItem(hir::TraitItem { - generics, - kind: hir::TraitItemKind::Method(..), .. - }) | - hir::Node::ImplItem(hir::ImplItem { - generics, - kind: hir::ImplItemKind::Method(..), .. - }) | - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Trait(_, _, generics, _, _), .. - }) | - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(_, _, _, generics, ..), .. - }) if projection.is_some() => { - // Missing associated type bound. - suggest_restriction(&generics, "the associated type"); - return; - } - - hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) | - hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) | - hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) | - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Trait(_, _, generics, ..), span, .. - }) | - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(_, _, _, generics, ..), span, .. - }) | - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(_, _, generics, _), span, .. - }) | - hir::Node::Item(hir::Item { - kind: hir::ItemKind::TyAlias(_, generics), span, .. - }) | - hir::Node::Item(hir::Item { - kind: hir::ItemKind::TraitAlias(generics, _), span, .. - }) | - hir::Node::Item(hir::Item { - kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }), span, .. - }) | - hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) | - hir::Node::ImplItem(hir::ImplItem { generics, span, .. }) - if param_ty => { - // Missing generic type parameter bound. - let restrict_msg = "consider further restricting this bound"; - let param_name = self_ty.to_string(); - for param in generics.params.iter().filter(|p| { - ¶m_name == std::convert::AsRef::::as_ref(&p.name.ident().as_str()) - }) { - if param_name.starts_with("impl ") { - // `impl Trait` in argument: - // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}` - err.span_suggestion( - param.span, - restrict_msg, - // `impl CurrentTrait + MissingTrait` - format!("{} + {}", param.name.ident(), trait_ref), - Applicability::MachineApplicable, - ); - } else if generics.where_clause.predicates.is_empty() && - param.bounds.is_empty() - { - // If there are no bounds whatsoever, suggest adding a constraint - // to the type parameter: - // `fn foo(t: T) {}` → `fn foo(t: T) {}` - err.span_suggestion( - param.span, - "consider restricting this bound", - format!("{}", trait_ref.to_predicate()), - Applicability::MachineApplicable, - ); - } else if !generics.where_clause.predicates.is_empty() { - // There is a `where` clause, so suggest expanding it: - // `fn foo(t: T) where T: Debug {}` → - // `fn foo(t: T) where T: Debug, T: Trait {}` - err.span_suggestion( - generics.where_clause.span().unwrap().shrink_to_hi(), - &format!( - "consider further restricting type parameter `{}`", - param_name, - ), - format!(", {}", trait_ref.to_predicate()), - Applicability::MachineApplicable, - ); - } else { - // If there is no `where` clause lean towards constraining to the - // type parameter: - // `fn foo(t: T, x: X) {}` → `fn foo(t: T) {}` - // `fn foo(t: T) {}` → `fn foo(t: T) {}` - let sp = param.span.with_hi(span.hi()); - let span = self.tcx.sess.source_map() - .span_through_char(sp, ':'); - if sp != param.span && sp != span { - // Only suggest if we have high certainty that the span - // covers the colon in `foo`. - err.span_suggestion(span, restrict_msg, format!( - "{} + ", - trait_ref.to_predicate(), - ), Applicability::MachineApplicable); - } else { - err.span_label(param.span, &format!( - "consider adding a `where {}` bound", - trait_ref.to_predicate(), - )); - } - } - return; - } - } - - hir::Node::Crate => return, - - _ => {} - } - - hir_id = self.tcx.hir().get_parent_item(hir_id); - } - } - /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a /// suggestion to borrow the initializer in order to use have a slice instead. fn suggest_borrow_on_unsized_slice( @@ -1250,11 +1070,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let substs = self.tcx.mk_substs_trait(trait_type, &[]); let new_trait_ref = ty::TraitRef::new(trait_ref.def_id, substs); - let new_obligation = Obligation::new( - ObligationCause::dummy(), - obligation.param_env, - new_trait_ref.to_predicate(), - ); + let new_obligation = Obligation::new(ObligationCause::dummy(), + obligation.param_env, + new_trait_ref.to_predicate()); if self.predicate_may_hold(&new_obligation) { let sp = self.tcx.sess.source_map() @@ -1276,77 +1094,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - /// Check if the trait bound is implemented for a different mutability and note it in the - /// final error. - fn suggest_change_mut( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut DiagnosticBuilder<'tcx>, - trait_ref: &ty::Binder>, - points_at_arg: bool, - ) { - let span = obligation.cause.span; - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - let refs_number = snippet.chars() - .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 trait_ref = self.resolve_vars_if_possible(trait_ref); - if trait_ref.has_infer_types() { - // Do not ICE while trying to find if a reborrow would succeed on a trait with - // unresolved bindings. - return; - } - - if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind { - let trait_type = match mutability { - hir::Mutability::MutMutable => self.tcx.mk_imm_ref(region, t_type), - hir::Mutability::MutImmutable => self.tcx.mk_mut_ref(region, t_type), - }; - - let substs = self.tcx.mk_substs_trait(&trait_type, &[]); - let new_trait_ref = ty::TraitRef::new(trait_ref.skip_binder().def_id, substs); - let new_obligation = Obligation::new( - ObligationCause::dummy(), - obligation.param_env, - new_trait_ref.to_predicate(), - ); - - if self.evaluate_obligation_no_overflow( - &new_obligation, - ).must_apply_modulo_regions() { - let sp = self.tcx.sess.source_map() - .span_take_while(span, |c| c.is_whitespace() || *c == '&'); - if points_at_arg && - mutability == hir::Mutability::MutImmutable && - refs_number > 0 - { - err.span_suggestion( - sp, - "consider changing this borrow's mutability", - "&mut ".to_string(), - Applicability::MachineApplicable, - ); - } else { - err.note(&format!( - "`{}` is implemented for `{:?}`, but not for `{:?}`", - trait_ref, - trait_type, - trait_ref.skip_binder().self_ty(), - )); - } - } - } - } - } - fn suggest_semicolon_removal( &self, obligation: &PredicateObligation<'tcx>, @@ -1657,7 +1404,11 @@ impl<'tcx> TyCtxt<'tcx> { span: Span, trait_def_id: DefId, violations: Vec, - ) -> DiagnosticBuilder<'tcx> { + ) -> Option> { + if self.sess.trait_methods_not_found.borrow().contains(&span) { + // Avoid emitting error caused by non-existing method (#58734) + return None; + } let trait_str = self.def_path_str(trait_def_id); let span = self.sess.source_map().def_span(span); let mut err = struct_span_err!( @@ -1675,13 +1426,7 @@ impl<'tcx> TyCtxt<'tcx> { }; } } - - if self.sess.trait_methods_not_found.borrow().contains(&span) { - // Avoid emitting error caused by non-existing method (#58734) - err.cancel(); - } - - err + Some(err) } } @@ -1859,165 +1604,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }) } - 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().kind); - match derived_obligation.parent_trait_ref.self_ty().kind { - 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 { - kind: 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(&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_code(&self, @@ -2092,10 +1687,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.note(&format!("required for the cast to the object type `{}`", self.ty_to_string(object_ty))); } - ObligationCauseCode::Coercion { source: _, target } => { - err.note(&format!("required by cast to type `{}`", - self.ty_to_string(target))); - } ObligationCauseCode::RepeatVec => { err.note("the `Copy` trait is required because the \ repeated element will be copied"); diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index eb4b114eb301c..accbbe3643ea1 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -188,9 +188,6 @@ pub enum ObligationCauseCode<'tcx> { /// Obligation incurred due to an object cast. ObjectCastObligation(/* Object type */ Ty<'tcx>), - /// Obligation incurred due to a coercion. - Coercion { source: Ty<'tcx>, target: Ty<'tcx> }, - // Various cases where expressions must be sized/copy/etc: /// L = X implies that L is Sized AssignmentLhsSized, @@ -613,7 +610,7 @@ pub struct VtableImplData<'tcx, N> { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] pub struct VtableGeneratorData<'tcx, N> { pub generator_def_id: DefId, - pub substs: SubstsRef<'tcx>, + pub substs: ty::GeneratorSubsts<'tcx>, /// Nested obligations. This can be non-empty if the generator /// signature contains associated types. pub nested: Vec @@ -622,7 +619,7 @@ pub struct VtableGeneratorData<'tcx, N> { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] pub struct VtableClosureData<'tcx, N> { pub closure_def_id: DefId, - pub substs: SubstsRef<'tcx>, + pub substs: ty::ClosureSubsts<'tcx>, /// Nested obligations. This can be non-empty if the closure /// signature contains associated types. pub nested: Vec diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index e42c3a63541cc..e0ef179911b6c 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -19,7 +19,7 @@ use crate::ty::subst::{Subst, InternalSubsts}; use std::borrow::Cow; use std::iter::{self}; use syntax::ast::{self}; -use syntax::symbol::Symbol; +use syntax::symbol::InternedString; use syntax_pos::{Span, DUMMY_SP}; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] @@ -560,7 +560,7 @@ impl<'tcx> TyCtxt<'tcx> { // are implemented let unsized_self_ty: Ty<'tcx> = self.mk_ty_param( ::std::u32::MAX, - Symbol::intern("RustaceansAreAwesome"), + InternedString::intern("RustaceansAreAwesome"), ); // `Receiver[Self => U]` diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index c1c814f9b0371..5a988d9509e80 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -250,7 +250,7 @@ impl<'tcx> OnUnimplementedFormatString { Position::ArgumentNamed(s) if s == sym::from_desugaring => (), // So is `{A}` if A is a type parameter Position::ArgumentNamed(s) => match generics.params.iter().find(|param| { - param.name == s + param.name.as_symbol() == s }) { Some(_) => (), None => { @@ -289,7 +289,7 @@ impl<'tcx> OnUnimplementedFormatString { }, GenericParamDefKind::Lifetime => return None }; - let name = param.name; + let name = param.name.as_symbol(); Some((name, value)) }).collect::>(); let empty_string = String::new(); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index d88bbe145d1fd..57077bcdffa72 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1259,7 +1259,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, vtable: VtableGeneratorData<'tcx, PredicateObligation<'tcx>>, ) -> Progress<'tcx> { - let gen_sig = vtable.substs.as_generator().poly_sig(vtable.generator_def_id, selcx.tcx()); + let gen_sig = vtable.substs.poly_sig(vtable.generator_def_id, selcx.tcx()); let Normalized { value: gen_sig, obligations @@ -1334,8 +1334,7 @@ fn confirm_closure_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { let tcx = selcx.tcx(); let infcx = selcx.infcx(); - let closure_sig_ty = vtable.substs - .as_closure().sig_ty(vtable.closure_def_id, tcx); + let closure_sig_ty = vtable.substs.closure_sig_ty(vtable.closure_def_id, tcx); let closure_sig = infcx.shallow_resolve(closure_sig_ty).fn_sig(tcx); let Normalized { value: closure_sig, @@ -1505,8 +1504,8 @@ fn assoc_ty_def( if let Some(assoc_item) = trait_def .ancestors(tcx, impl_def_id) - .leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) { - + .defs(tcx, assoc_ty_name, ty::AssocKind::Type, trait_def_id) + .next() { assoc_item } else { // This is saying that neither the trait nor diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index e84c91daf293f..aa30541610e9b 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -5,7 +5,6 @@ use std::iter::FromIterator; use syntax::source_map::Span; use crate::ty::subst::GenericArg; use crate::ty::{self, Ty, TyCtxt}; -use crate::ty::query::Providers; impl<'cx, 'tcx> At<'cx, 'tcx> { /// Given a type `ty` of some value being dropped, computes a set @@ -34,7 +33,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> { // Quick check: there are a number of cases that we know do not require // any destructor. let tcx = self.infcx.tcx; - if tcx.trivial_dropck_outlives(ty) { + if trivial_dropck_outlives(tcx, ty) { return InferOk { value: vec![], obligations: vec![], @@ -208,15 +207,14 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { | ty::Error => true, // [T; N] and [T] have same properties as T. - ty::Array(ty, _) | ty::Slice(ty) => tcx.trivial_dropck_outlives(ty), + ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty), // (T1..Tn) and closures have same properties as T1..Tn -- // check if *any* of those are trivial. - ty::Tuple(ref tys) => tys.iter().all(|t| tcx.trivial_dropck_outlives(t.expect_ty())), + ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())), ty::Closure(def_id, ref substs) => substs - .as_closure() .upvar_tys(def_id, tcx) - .all(|t| tcx.trivial_dropck_outlives(t)), + .all(|t| trivial_dropck_outlives(tcx, t)), ty::Adt(def, _) => { if Some(def.did) == tcx.lang_items().manually_drop() { @@ -244,10 +242,3 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } - -crate fn provide(p: &mut Providers<'_>) { - *p = Providers { - trivial_dropck_outlives, - ..*p - }; -} diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs index 0d426cab9b751..17684df7e9b8e 100644 --- a/src/librustc/traits/query/evaluate_obligation.rs +++ b/src/librustc/traits/query/evaluate_obligation.rs @@ -56,7 +56,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // Helper function that canonicalizes and runs the query. If an // overflow results, we re-run it in the local context so we can // report a nice error. - crate fn evaluate_obligation_no_overflow( + fn evaluate_obligation_no_overflow( &self, obligation: &PredicateObligation<'tcx>, ) -> EvaluationResult { diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs index f6ea77dc5cc68..112a1d0e09c94 100644 --- a/src/librustc/traits/query/mod.rs +++ b/src/librustc/traits/query/mod.rs @@ -40,7 +40,7 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> = pub type CanonicalTypeOpNormalizeGoal<'tcx, T> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::normalize::Normalize>>; -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct NoSolution; pub type Fallible = Result; diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs index eee084b78963c..f5808b6b5faaf 100644 --- a/src/librustc/traits/query/outlives_bounds.rs +++ b/src/librustc/traits/query/outlives_bounds.rs @@ -7,7 +7,8 @@ use crate::traits::query::NoSolution; use crate::ty::{self, Ty, TyCtxt}; use crate::ich::StableHashingContext; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, + StableHasherResult}; use std::mem; /// Outlives bounds are relationships between generic parameters, @@ -42,7 +43,9 @@ EnumTypeFoldableImpl! { } impl<'a, 'tcx> HashStable> for OutlivesBound<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { OutlivesBound::RegionSubRegion(ref a, ref b) => { diff --git a/src/librustc/traits/query/type_op/implied_outlives_bounds.rs b/src/librustc/traits/query/type_op/implied_outlives_bounds.rs index 7aa98703411b2..12a834fbda6bd 100644 --- a/src/librustc/traits/query/type_op/implied_outlives_bounds.rs +++ b/src/librustc/traits/query/type_op/implied_outlives_bounds.rs @@ -3,7 +3,7 @@ use crate::traits::query::outlives_bounds::OutlivesBound; use crate::traits::query::Fallible; use crate::ty::{ParamEnvAnd, Ty, TyCtxt}; -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct ImpliedOutlivesBounds<'tcx> { pub ty: Ty<'tcx>, } diff --git a/src/librustc/traits/query/type_op/outlives.rs b/src/librustc/traits/query/type_op/outlives.rs index 86a32d68fc09e..9b956f3e55408 100644 --- a/src/librustc/traits/query/type_op/outlives.rs +++ b/src/librustc/traits/query/type_op/outlives.rs @@ -1,4 +1,5 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse}; +use crate::traits::query::dropck_outlives::trivial_dropck_outlives; use crate::traits::query::dropck_outlives::DropckOutlivesResult; use crate::traits::query::Fallible; use crate::ty::{ParamEnvAnd, Ty, TyCtxt}; @@ -21,7 +22,7 @@ impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> { tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>, ) -> Option { - if tcx.trivial_dropck_outlives(key.value.dropped_ty) { + if trivial_dropck_outlives(tcx, key.value.dropped_ty) { Some(DropckOutlivesResult::default()) } else { None diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index d8a27f1e04051..e1ca9a16d965f 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -40,7 +40,7 @@ use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable}; use crate::hir; -use rustc_index::bit_set::GrowableBitSet; +use rustc_data_structures::bit_set::GrowableBitSet; use rustc_data_structures::sync::Lock; use rustc_target::spec::abi::Abi; use syntax::attr; @@ -2051,10 +2051,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { "assemble_unboxed_candidates: kind={:?} obligation={:?}", kind, obligation ); - match self.infcx.closure_kind( - closure_def_id, - closure_substs - ) { + match self.infcx.closure_kind(closure_def_id, closure_substs) { Some(closure_kind) => { debug!( "assemble_unboxed_candidates: closure_kind = {:?}", @@ -2246,13 +2243,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if let Some(principal) = data.principal() { - if !self.infcx.tcx.features().object_safe_for_dispatch { - principal.with_self_ty(self.tcx(), self_ty) - } else if self.tcx().is_object_safe(principal.def_id()) { - principal.with_self_ty(self.tcx(), self_ty) - } else { - return; - } + principal.with_self_ty(self.tcx(), self_ty) } else { // Only auto-trait bounds exist. return; @@ -2678,7 +2669,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Closure(def_id, substs) => { // (*) binder moved here Where(ty::Binder::bind( - substs.as_closure().upvar_tys(def_id, self.tcx()).collect(), + substs.upvar_tys(def_id, self.tcx()).collect(), )) } @@ -2762,14 +2753,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { tys.iter().map(|k| k.expect_ty()).collect() } - ty::Closure(def_id, ref substs) => substs.as_closure() - .upvar_tys(def_id, self.tcx()) - .collect(), + ty::Closure(def_id, ref substs) => substs.upvar_tys(def_id, self.tcx()).collect(), ty::Generator(def_id, ref substs, _) => { - let witness = substs.as_generator().witness(def_id, self.tcx()); + let witness = substs.witness(def_id, self.tcx()); substs - .as_generator() .upvar_tys(def_id, self.tcx()) .chain(iter::once(witness)) .collect() @@ -2825,7 +2813,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // binder moved -\ let ty: ty::Binder> = ty::Binder::bind(ty); // <----/ - self.infcx.commit_unconditionally(|_| { + self.infcx.in_snapshot(|_| { let (skol_ty, _) = self.infcx .replace_bound_vars_with_placeholders(&ty); let Normalized { @@ -2938,7 +2926,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { - self.infcx.commit_unconditionally(|snapshot| { + self.infcx.in_snapshot(|snapshot| { let result = self.match_projection_obligation_against_definition_bounds( obligation, @@ -3060,20 +3048,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nested, ); - let trait_obligations: Vec> = - self.infcx.commit_unconditionally(|_| { - let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let (trait_ref, _) = self.infcx - .replace_bound_vars_with_placeholders(&poly_trait_ref); - let cause = obligation.derived_cause(ImplDerivedObligation); - self.impl_or_trait_obligations( - cause, - obligation.recursion_depth + 1, - obligation.param_env, - trait_def_id, - &trait_ref.substs, - ) - }); + let trait_obligations: Vec> = self.infcx.in_snapshot(|_| { + let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); + let (trait_ref, _) = self.infcx + .replace_bound_vars_with_placeholders(&poly_trait_ref); + let cause = obligation.derived_cause(ImplDerivedObligation); + self.impl_or_trait_obligations( + cause, + obligation.recursion_depth + 1, + obligation.param_env, + trait_def_id, + &trait_ref.substs, + ) + }); // Adds the predicates from the trait. Note that this contains a `Self: Trait` // predicate as usual. It won't have any effect since auto traits are coinductive. @@ -3096,7 +3083,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // First, create the substitutions by matching the impl again, // this time not in a probe. - self.infcx.commit_unconditionally(|snapshot| { + self.infcx.in_snapshot(|snapshot| { let substs = self.rematch_impl(impl_def_id, obligation, snapshot); debug!("confirm_impl_candidate: substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); @@ -3260,7 +3247,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation, alias_def_id ); - self.infcx.commit_unconditionally(|_| { + self.infcx.in_snapshot(|_| { let (predicate, _) = self.infcx() .replace_bound_vars_with_placeholders(&obligation.predicate); let trait_ref = predicate.trait_ref; @@ -3332,8 +3319,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { )?); Ok(VtableGeneratorData { - generator_def_id, - substs, + generator_def_id: generator_def_id, + substs: substs.clone(), nested: obligations, }) } @@ -3383,22 +3370,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { )?); // FIXME: chalk - if !self.tcx().sess.opts.debugging_opts.chalk { obligations.push(Obligation::new( obligation.cause.clone(), obligation.param_env, - ty::Predicate::ClosureKind( - closure_def_id, - substs, - kind - ), + ty::Predicate::ClosureKind(closure_def_id, substs, kind), )); } Ok(VtableClosureData { closure_def_id, - substs: substs, + substs: substs.clone(), nested: obligations, }) } @@ -3887,7 +3869,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, closure_def_id: DefId, - substs: SubstsRef<'tcx>, + substs: ty::ClosureSubsts<'tcx>, ) -> ty::PolyTraitRef<'tcx> { debug!( "closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})", @@ -3919,9 +3901,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, closure_def_id: DefId, - substs: SubstsRef<'tcx>, + substs: ty::GeneratorSubsts<'tcx>, ) -> ty::PolyTraitRef<'tcx> { - let gen_sig = substs.as_generator().poly_sig(closure_def_id, self.tcx()); + let gen_sig = substs.poly_sig(closure_def_id, self.tcx()); // (1) Feels icky to skip the binder here, but OTOH we know // that the self-type is an generator type and hence is diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index c1c6eb850f591..f0389bb037ac5 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -125,7 +125,7 @@ pub fn find_associated_item<'tcx>( let trait_def = tcx.trait_def(trait_def_id); let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id); - match ancestors.leaf_def(tcx, item.ident, item.kind) { + match ancestors.defs(tcx, item.ident, item.kind, trait_def_id).next() { Some(node_item) => { let substs = tcx.infer_ctxt().enter(|infcx| { let param_env = param_env.with_reveal_all(); @@ -419,7 +419,7 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option // The predicates will contain default bounds like `T: Sized`. We need to // remove these bounds, and add `T: ?Sized` to any untouched type parameters. - let predicates = tcx.predicates_of(impl_def_id).predicates; + let predicates = &tcx.predicates_of(impl_def_id).predicates; let mut pretty_predicates = Vec::with_capacity( predicates.len() + types_without_default_bounds.len()); diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index c64d6748ea97d..ce0f43021378b 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -2,11 +2,13 @@ use super::OverlapError; use crate::hir::def_id::DefId; use crate::ich::{self, StableHashingContext}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, + StableHasherResult}; use crate::traits; use crate::ty::{self, TyCtxt, TypeFoldable}; use crate::ty::fast_reject::{self, SimplifiedType}; use syntax::ast::Ident; +use crate::util::captures::Captures; use crate::util::nodemap::{DefIdMap, FxHashMap}; /// A per-trait graph of impls in specialization order. At the moment, this @@ -418,35 +420,6 @@ impl<'tcx> Node { tcx.associated_items(self.def_id()) } - /// Finds an associated item defined in this node. - /// - /// If this returns `None`, the item can potentially still be found in - /// parents of this node. - pub fn item( - &self, - tcx: TyCtxt<'tcx>, - trait_item_name: Ident, - trait_item_kind: ty::AssocKind, - trait_def_id: DefId, - ) -> Option { - use crate::ty::AssocKind::*; - - tcx.associated_items(self.def_id()) - .find(move |impl_item| match (trait_item_kind, impl_item.kind) { - | (Const, Const) - | (Method, Method) - | (Type, Type) - | (Type, OpaqueTy) // assoc. types can be made opaque in impls - => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id), - - | (Const, _) - | (Method, _) - | (Type, _) - | (OpaqueTy, _) - => false, - }) - } - pub fn def_id(&self) -> DefId { match *self { Node::Impl(did) => did, @@ -455,7 +428,6 @@ impl<'tcx> Node { } } -#[derive(Copy, Clone)] pub struct Ancestors<'tcx> { trait_def_id: DefId, specialization_graph: &'tcx Graph, @@ -494,18 +466,32 @@ impl NodeItem { } impl<'tcx> Ancestors<'tcx> { - /// Finds the bottom-most (ie. most specialized) definition of an associated - /// item. - pub fn leaf_def( - mut self, + /// Search the items from the given ancestors, returning each definition + /// with the given name and the given kind. + // FIXME(#35870): avoid closures being unexported due to `impl Trait`. + #[inline] + pub fn defs( + self, tcx: TyCtxt<'tcx>, trait_item_name: Ident, trait_item_kind: ty::AssocKind, - ) -> Option> { - let trait_def_id = self.trait_def_id; - self.find_map(|node| { - node.item(tcx, trait_item_name, trait_item_kind, trait_def_id) - .map(|item| NodeItem { node, item }) + trait_def_id: DefId, + ) -> impl Iterator> + Captures<'tcx> + 'tcx { + self.flat_map(move |node| { + use crate::ty::AssocKind::*; + node.items(tcx).filter(move |impl_item| match (trait_item_kind, impl_item.kind) { + | (Const, Const) + | (Method, Method) + | (Type, Type) + | (Type, OpaqueTy) + => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id), + + | (Const, _) + | (Method, _) + | (Type, _) + | (OpaqueTy, _) + => false, + }).map(move |item| NodeItem { node: node, item: item }) }) } } @@ -526,7 +512,9 @@ pub fn ancestors( } impl<'a> HashStable> for Children { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let Children { ref nonblanket_impls, ref blanket_impls, diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 18db3c8d10b7c..dab62a6bcb5b1 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -4,7 +4,7 @@ use crate::traits; use crate::traits::project::Normalized; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::{self, Lift, Ty, TyCtxt}; -use syntax::symbol::Symbol; +use syntax::symbol::InternedString; use std::fmt; use std::rc::Rc; @@ -261,11 +261,11 @@ impl fmt::Display for traits::QuantifierKind { /// for debug output in tests anyway. struct BoundNamesCollector { // Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway. - regions: BTreeSet, + regions: BTreeSet, // Sort by `BoundVar` index, so usually this should be equivalent to the order given // by the list of type parameters. - types: BTreeMap, + types: BTreeMap, binder_index: ty::DebruijnIndex, } @@ -319,7 +319,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector { match bound_ty.kind { ty::BoundTyKind::Param(name) => name, ty::BoundTyKind::Anon => - Symbol::intern(&format!("^{}", bound_ty.var.as_u32()), + InternedString::intern(&format!("^{}", bound_ty.var.as_u32()), ), } ); @@ -340,7 +340,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector { } ty::BoundRegion::BrAnon(var) => { - self.regions.insert(Symbol::intern(&format!("'^{}", var))); + self.regions.insert(InternedString::intern(&format!("'^{}", var))); } _ => (), @@ -481,10 +481,6 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { .and_then(|r| Some(super::ObjectTypeBound(ty, r))) ), super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation), - super::Coercion { source, target } => Some(super::Coercion { - source: tcx.lift(&source)?, - target: tcx.lift(&target)?, - }), super::AssignmentLhsSized => Some(super::AssignmentLhsSized), super::TupleInitializerSized => Some(super::TupleInitializerSized), super::StructInitializerSized => Some(super::StructInitializerSized), diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index d8b1effe09bf4..18ec2241b2df8 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -4,6 +4,7 @@ use syntax_pos::Span; use crate::hir; use crate::hir::def_id::DefId; +use crate::traits::specialize::specialization_graph::NodeItem; use crate::ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef}; use crate::ty::outlives::Component; use crate::ty::subst::{GenericArg, Subst, SubstsRef}; @@ -666,8 +667,8 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn impl_item_is_final(self, assoc_item: &ty::AssocItem) -> bool { - assoc_item.defaultness.is_final() && !self.impl_is_default(assoc_item.container.id()) + pub fn impl_item_is_final(self, node_item: &NodeItem) -> bool { + node_item.item.is_final() && !self.impl_is_default(node_item.node.def_id()) } } diff --git a/src/librustc/ty/binding.rs b/src/librustc/ty/binding.rs index 5570144489cdf..1290141b0a6b0 100644 --- a/src/librustc/ty/binding.rs +++ b/src/librustc/ty/binding.rs @@ -2,7 +2,7 @@ use crate::hir::BindingAnnotation::*; use crate::hir::BindingAnnotation; use crate::hir::Mutability; -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum BindingMode { BindByReference(Mutability), BindByValue(Mutability), diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index d5e7ac19263a0..bd4913c88fd1f 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -13,10 +13,9 @@ use rustc_data_structures::fx::FxHashMap; use rustc_serialize::{Decodable, Decoder, Encoder, Encodable, opaque}; use std::hash::Hash; use std::intrinsics; -use crate::ty::{self, List, Ty, TyCtxt}; +use crate::ty::{self, Ty, TyCtxt}; use crate::ty::subst::SubstsRef; -use crate::mir::{self, interpret::Allocation}; -use syntax_pos::Span; +use crate::mir::interpret::Allocation; /// The shorthand encoding uses an enum's variant index `usize` /// and is offset by this value so it never matches a real variant. @@ -93,16 +92,16 @@ pub fn encode_with_shorthand(encoder: &mut E, Ok(()) } -pub fn encode_spanned_predicates<'tcx, E, C>( - encoder: &mut E, - predicates: &'tcx [(ty::Predicate<'tcx>, Span)], - cache: C, -) -> Result<(), E::Error> +pub fn encode_predicates<'tcx, E, C>(encoder: &mut E, + predicates: &ty::GenericPredicates<'tcx>, + cache: C) + -> Result<(), E::Error> where E: TyEncoder, C: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap, usize>, { - predicates.len().encode(encoder)?; - for (predicate, span) in predicates { + predicates.parent.encode(encoder)?; + predicates.predicates.len().encode(encoder)?; + for (predicate, span) in &predicates.predicates { encode_with_shorthand(encoder, predicate, &cache)?; span.encode(encoder)?; } @@ -183,15 +182,13 @@ where } #[inline] -pub fn decode_spanned_predicates( - decoder: &mut D, -) -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], D::Error> +pub fn decode_predicates(decoder: &mut D) -> Result, D::Error> where D: TyDecoder<'tcx>, { - let tcx = decoder.tcx(); - Ok(tcx.arena.alloc_from_iter( - (0..decoder.read_usize()?).map(|_| { + Ok(ty::GenericPredicates { + parent: Decodable::decode(decoder)?, + predicates: (0..decoder.read_usize()?).map(|_| { // Handle shorthands first, if we have an usize > 0x80. let predicate = if decoder.positioned_at_shorthand() { let pos = decoder.read_usize()?; @@ -205,7 +202,7 @@ where Ok((predicate, Decodable::decode(decoder)?)) }) .collect::, _>>()?, - )) + }) } #[inline] @@ -218,18 +215,6 @@ where Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?) } -#[inline] -pub fn decode_place(decoder: &mut D) -> Result, D::Error> -where - D: TyDecoder<'tcx>, -{ - let base: mir::PlaceBase<'tcx> = Decodable::decode(decoder)?; - let len = decoder.read_usize()?; - let projection: &'tcx List> = - decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?; - Ok(mir::Place { base, projection }) -} - #[inline] pub fn decode_region(decoder: &mut D) -> Result, D::Error> where @@ -354,8 +339,6 @@ macro_rules! implement_ty_decoder { use $crate::ty::subst::SubstsRef; use $crate::hir::def_id::{CrateNum}; - use syntax_pos::Span; - use super::$DecoderName; impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> { @@ -410,11 +393,11 @@ macro_rules! implement_ty_decoder { } } - impl<$($typaram),*> SpecializedDecoder<&'tcx [(ty::Predicate<'tcx>, Span)]> + impl<$($typaram),*> SpecializedDecoder> for $DecoderName<$($typaram),*> { fn specialized_decode(&mut self) - -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], Self::Error> { - decode_spanned_predicates(self) + -> Result, Self::Error> { + decode_predicates(self) } } @@ -425,15 +408,6 @@ macro_rules! implement_ty_decoder { } } - impl<$($typaram),*> SpecializedDecoder<$crate::mir::Place<'tcx>> - for $DecoderName<$($typaram),*> { - fn specialized_decode( - &mut self - ) -> Result<$crate::mir::Place<'tcx>, Self::Error> { - decode_place(self) - } - } - impl<$($typaram),*> SpecializedDecoder> for $DecoderName<$($typaram),*> { fn specialized_decode(&mut self) -> Result, Self::Error> { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index f958a7e357b39..efbc820365e2d 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1,4 +1,3 @@ -// ignore-tidy-filelength //! Type context book-keeping. use crate::arena::Arena; @@ -22,7 +21,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, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted}; +use crate::mir::{Body, interpret, ProjectionKind, Promoted}; use crate::mir::interpret::{ConstValue, Allocation, Scalar}; use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef, Subst}; use crate::ty::ReprOptions; @@ -30,7 +29,7 @@ use crate::traits; use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals}; use crate::ty::{self, DefIdTree, Ty, TypeAndMut}; use crate::ty::{TyS, TyKind, List}; -use crate::ty::{AdtKind, AdtDef, Region, Const}; +use crate::ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const}; use crate::ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate}; use crate::ty::RegionKind; use crate::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid, ConstVid}; @@ -44,17 +43,16 @@ use crate::ty::subst::{UserSubsts, GenericArgKind}; use crate::ty::{BoundVar, BindingMode}; use crate::ty::CanonicalPolyFnSig; use crate::util::common::ErrorReported; -use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet, NodeMap}; +use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet}; use crate::util::nodemap::{FxHashMap, FxHashSet}; -use crate::util::profiling::SelfProfilerRef; use errors::DiagnosticBuilder; use arena::SyncDroplessArena; use smallvec::SmallVec; use rustc_data_structures::stable_hasher::{ - HashStable, StableHasher, StableVec, hash_stable_hashmap, + HashStable, StableHasher, StableHasherResult, StableVec, hash_stable_hashmap, }; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::sharded::ShardedHashMap; use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal}; use std::any::Any; @@ -73,7 +71,7 @@ use syntax::ast; use syntax::attr; use syntax::source_map::MultiSpan; use syntax::feature_gate; -use syntax::symbol::{Symbol, kw, sym}; +use syntax::symbol::{Symbol, InternedString, kw, sym}; use syntax_pos::Span; pub struct AllArenas { @@ -107,7 +105,6 @@ pub struct CtxtInterners<'tcx> { goal: InternedSet<'tcx, GoalKind<'tcx>>, goal_list: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, - place_elems: InternedSet<'tcx, List>>, const_: InternedSet<'tcx, Const<'tcx>>, } @@ -126,7 +123,6 @@ impl<'tcx> CtxtInterners<'tcx> { goal: Default::default(), goal_list: Default::default(), projs: Default::default(), - place_elems: Default::default(), const_: Default::default(), } } @@ -151,6 +147,10 @@ impl<'tcx> CtxtInterners<'tcx> { } } +pub struct Common<'tcx> { + pub empty_predicates: ty::GenericPredicates<'tcx>, +} + pub struct CommonTypes<'tcx> { pub unit: Ty<'tcx>, pub bool: Ty<'tcx>, @@ -288,40 +288,6 @@ 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. @@ -431,10 +397,6 @@ 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> { @@ -460,7 +422,6 @@ impl<'tcx> TypeckTables<'tcx> { free_region_map: Default::default(), concrete_opaque_types: Default::default(), upvar_list: Default::default(), - generator_interior_types: Default::default(), } } @@ -744,7 +705,9 @@ impl<'tcx> TypeckTables<'tcx> { } impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let ty::TypeckTables { local_id_root, ref type_dependent_defs, @@ -768,7 +731,6 @@ impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { ref free_region_map, ref concrete_opaque_types, ref upvar_list, - ref generator_interior_types, } = *self; @@ -813,12 +775,11 @@ 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); }) } } -rustc_index::newtype_index! { +newtype_index! { pub struct UserTypeAnnotationIndex { derive [HashStable] DEBUG_FORMAT = "UserType({})", @@ -830,7 +791,7 @@ rustc_index::newtype_index! { pub type CanonicalUserTypeAnnotations<'tcx> = IndexVec>; -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct CanonicalUserTypeAnnotation<'tcx> { pub user_ty: CanonicalUserType<'tcx>, pub span: Span, @@ -885,7 +846,7 @@ impl CanonicalUserType<'tcx> { }, GenericArgKind::Const(ct) => match ct.val { - ConstValue::Bound(debruijn, b) => { + ConstValue::Infer(InferConst::Canonical(debruijn, b)) => { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(debruijn, ty::INNERMOST); cvar == b @@ -902,7 +863,7 @@ impl CanonicalUserType<'tcx> { /// A user-given type annotation attached to a constant. These arise /// from constants that are named via paths, like `Foo::::new` and /// so forth. -#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub enum UserType<'tcx> { Ty(Ty<'tcx>), @@ -952,7 +913,7 @@ impl<'tcx> CommonTypes<'tcx> { f64: mk(Float(ast::FloatTy::F64)), self_param: mk(ty::Param(ty::ParamTy { index: 0, - name: kw::SelfUpper, + name: kw::SelfUpper.as_interned_str(), })), trait_object_dummy_self: mk(Infer(ty::FreshTy(0))), @@ -1030,15 +991,14 @@ pub struct GlobalCtxt<'tcx> { interners: CtxtInterners<'tcx>, - cstore: Box, + cstore: &'tcx CrateStoreDyn, pub sess: &'tcx Session, - pub lint_store: Lrc, - pub dep_graph: DepGraph, - pub prof: SelfProfilerRef, + /// Common objects. + pub common: Common<'tcx>, /// Common types, pre-interned for your convenience. pub types: CommonTypes<'tcx>, @@ -1049,9 +1009,6 @@ pub struct GlobalCtxt<'tcx> { /// Common consts, pre-interned for your convenience. pub consts: CommonConsts<'tcx>, - /// Resolutions of `extern crate` items produced by resolver. - extern_crate_map: NodeMap, - /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. trait_map: FxHashMap TyCtxt<'tcx> { /// reference to the context, to allow formatting values that need it. pub fn create_global_ctxt( s: &'tcx Session, - lint_store: Lrc, + cstore: &'tcx CrateStoreDyn, local_providers: ty::query::Providers<'tcx>, extern_providers: ty::query::Providers<'tcx>, arenas: &'tcx AllArenas, - resolutions: ty::ResolverOutputs, + resolutions: ty::Resolutions, hir: hir_map::Map<'tcx>, on_disk_query_result_cache: query::OnDiskCache<'tcx>, crate_name: &str, @@ -1211,32 +1168,44 @@ impl<'tcx> TyCtxt<'tcx> { s.fatal(&err); }); let interners = CtxtInterners::new(&arenas.interner); + let common = Common { + empty_predicates: ty::GenericPredicates { + parent: None, + predicates: vec![], + }, + }; let common_types = CommonTypes::new(&interners); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); let dep_graph = hir.dep_graph.clone(); - let cstore = resolutions.cstore; - let crates = cstore.crates_untracked(); - let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0); + let max_cnum = cstore.crates_untracked().iter().map(|c| c.as_usize()).max().unwrap_or(0); let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); providers[LOCAL_CRATE] = local_providers; let def_path_hash_to_def_id = if s.opts.build_dep_graph() { - let def_path_tables = crates + let upstream_def_path_tables: Vec<(CrateNum, Lrc<_>)> = cstore + .crates_untracked() .iter() .map(|&cnum| (cnum, cstore.def_path_table(cnum))) - .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table()))); + .collect(); + + let def_path_tables = || { + upstream_def_path_tables + .iter() + .map(|&(cnum, ref rc)| (cnum, &**rc)) + .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table()))) + }; // Precompute the capacity of the hashmap so we don't have to // re-allocate when populating it. - let capacity = def_path_tables.clone().map(|(_, t)| t.size()).sum::(); + let capacity = def_path_tables().map(|(_, t)| t.size()).sum::(); let mut map: FxHashMap<_, _> = FxHashMap::with_capacity_and_hasher( capacity, ::std::default::Default::default() ); - for (cnum, def_path_table) in def_path_tables { + for (cnum, def_path_table) in def_path_tables() { def_path_table.add_def_path_hashes_to(cnum, &mut map); } @@ -1254,16 +1223,14 @@ impl<'tcx> TyCtxt<'tcx> { GlobalCtxt { sess: s, - lint_store, cstore, arena: WorkerLocal::new(|_| Arena::default()), interners, dep_graph, - prof: s.prof.clone(), + common, types: common_types, lifetimes: common_lifetimes, consts: common_consts, - extern_crate_map: resolutions.extern_crate_map, trait_map, export_map: resolutions.export_map.into_iter().map(|(k, v)| { let exports: Vec<_> = v.into_iter().map(|e| { @@ -1413,8 +1380,8 @@ impl<'tcx> TyCtxt<'tcx> { // 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_any(self, cnum: CrateNum) -> &'tcx dyn Any { - self.cstore.crate_data_as_any(cnum) + pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Lrc { + self.cstore.crate_data_as_rc_any(cnum) } #[inline(always)] @@ -1424,7 +1391,7 @@ impl<'tcx> TyCtxt<'tcx> { StableHashingContext::new(self.sess, krate, self.hir().definitions(), - &*self.cstore) + self.cstore) } // This method makes sure that we have a DepNode and a Fingerprint for @@ -2145,13 +2112,6 @@ impl<'tcx> Borrow<[ProjectionKind]> } } -impl<'tcx> Borrow<[PlaceElem<'tcx>]> - for Interned<'tcx, List>> { - fn borrow(&self) -> &[PlaceElem<'tcx>] { - &self.0[..] - } -} - impl<'tcx> Borrow for Interned<'tcx, RegionKind> { fn borrow(&self) -> &RegionKind { &self.0 @@ -2196,29 +2156,44 @@ impl<'tcx> Borrow<[Goal<'tcx>]> for Interned<'tcx, List>> { } } +macro_rules! intern_method { + ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty, + $alloc_method:expr, + $alloc_to_key:expr) -> $ty:ty) => { + impl<$lt_tcx> TyCtxt<$lt_tcx> { + pub fn $method(self, v: $alloc) -> &$lt_tcx $ty { + let key = ($alloc_to_key)(&v); + + self.interners.$name.intern_ref(key, || { + Interned($alloc_method(&self.interners.arena, v)) + + }).0 + } + } + } +} + macro_rules! direct_interners { - ($($name:ident: $method:ident($ty:ty)),+) => { - $(impl<'tcx> PartialEq for Interned<'tcx, $ty> { + ($lt_tcx:tt, $($name:ident: $method:ident($ty:ty)),+) => { + $(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> { fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } - impl<'tcx> Eq for Interned<'tcx, $ty> {} + impl<$lt_tcx> Eq for Interned<$lt_tcx, $ty> {} - impl<'tcx> Hash for Interned<'tcx, $ty> { + impl<$lt_tcx> Hash for Interned<$lt_tcx, $ty> { fn hash(&self, s: &mut H) { self.0.hash(s) } } - impl<'tcx> TyCtxt<'tcx> { - pub fn $method(self, v: $ty) -> &'tcx $ty { - self.interners.$name.intern_ref(&v, || { - Interned(self.interners.arena.alloc(v)) - }).0 - } - })+ + intern_method!( + $lt_tcx, + $name: $method($ty, + |a: &$lt_tcx SyncDroplessArena, v| -> &$lt_tcx $ty { a.alloc(v) }, + |x| x) -> $ty);)+ } } @@ -2226,7 +2201,7 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { x.has_type_flags(ty::TypeFlags::KEEP_IN_LOCAL_TCX) } -direct_interners!( +direct_interners!('tcx, region: mk_region(RegionKind), goal: mk_goal(GoalKind<'tcx>), const_: mk_const(Const<'tcx>) @@ -2234,28 +2209,37 @@ direct_interners!( macro_rules! slice_interners { ($($field:ident: $method:ident($ty:ty)),+) => ( - $(impl<'tcx> TyCtxt<'tcx> { - pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> { - self.interners.$field.intern_ref(v, || { - Interned(List::from_arena(&self.interners.arena, v)) - }).0 - } - })+ + $(intern_method!( 'tcx, $field: $method( + &[$ty], + |a, v| List::from_arena(a, v), + Deref::deref) -> List<$ty>);)+ ); } slice_interners!( - type_list: _intern_type_list(Ty<'tcx>), - substs: _intern_substs(GenericArg<'tcx>), - canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo), existential_predicates: _intern_existential_predicates(ExistentialPredicate<'tcx>), predicates: _intern_predicates(Predicate<'tcx>), + type_list: _intern_type_list(Ty<'tcx>), + substs: _intern_substs(GenericArg<'tcx>), clauses: _intern_clauses(Clause<'tcx>), goal_list: _intern_goals(Goal<'tcx>), - projs: _intern_projs(ProjectionKind), - place_elems: _intern_place_elems(PlaceElem<'tcx>) + projs: _intern_projs(ProjectionKind) ); +// This isn't a perfect fit: `CanonicalVarInfo` slices are always +// allocated in the global arena, so this `intern_method!` macro is +// 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! { + 'tcx, + canonical_var_infos: _intern_canonical_var_infos( + &[CanonicalVarInfo], + |a, v| List::from_arena(a, v), + Deref::deref + ) -> List +} + impl<'tcx> TyCtxt<'tcx> { /// Given a `fn` type, returns an equivalent `unsafe fn` type; /// that is, a `fn` type that is equivalent in every way for being @@ -2500,7 +2484,7 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_closure(self, closure_id: DefId, closure_substs: SubstsRef<'tcx>) + pub fn mk_closure(self, closure_id: DefId, closure_substs: ClosureSubsts<'tcx>) -> Ty<'tcx> { self.mk_ty(Closure(closure_id, closure_substs)) } @@ -2508,7 +2492,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_generator(self, id: DefId, - generator_substs: SubstsRef<'tcx>, + generator_substs: GeneratorSubsts<'tcx>, movability: hir::GeneratorMovability) -> Ty<'tcx> { self.mk_ty(Generator(id, generator_substs, movability)) @@ -2560,7 +2544,7 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> { + pub fn mk_ty_param(self, index: u32, name: InternedString) -> Ty<'tcx> { self.mk_ty(Param(ParamTy { index, name: name })) } @@ -2568,7 +2552,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn mk_const_param( self, index: u32, - name: Symbol, + name: InternedString, ty: Ty<'tcx> ) -> &'tcx Const<'tcx> { self.mk_const(ty::Const { @@ -2595,48 +2579,6 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_ty(Opaque(def_id, substs)) } - pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> { - self.mk_place_elem(place, PlaceElem::Field(f, ty)) - } - - pub fn mk_place_deref(self, place: Place<'tcx>) -> Place<'tcx> { - self.mk_place_elem(place, PlaceElem::Deref) - } - - pub fn mk_place_downcast( - self, - place: Place<'tcx>, - adt_def: &'tcx AdtDef, - variant_index: VariantIdx, - ) -> Place<'tcx> { - self.mk_place_elem( - place, - PlaceElem::Downcast(Some(adt_def.variants[variant_index].ident.name), variant_index), - ) - } - - pub fn mk_place_downcast_unnamed( - self, - place: Place<'tcx>, - variant_index: VariantIdx, - ) -> Place<'tcx> { - self.mk_place_elem(place, PlaceElem::Downcast(None, variant_index)) - } - - pub fn mk_place_index(self, place: Place<'tcx>, index: Local) -> Place<'tcx> { - self.mk_place_elem(place, PlaceElem::Index(index)) - } - - /// This method copies `Place`'s projection, add an element and reintern it. Should not be used - /// to build a full `Place` it's just a convenient way to grab a projection and modify it in - /// flight. - pub fn mk_place_elem(self, place: Place<'tcx>, elem: PlaceElem<'tcx>) -> Place<'tcx> { - let mut projection = place.projection.to_vec(); - projection.push(elem); - - Place { base: place.base, projection: self.intern_place_elems(&projection) } - } - pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>]) -> &'tcx List> { assert!(!eps.is_empty()); @@ -2681,14 +2623,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn intern_place_elems(self, ts: &[PlaceElem<'tcx>]) -> &'tcx List> { - if ts.len() == 0 { - List::empty() - } else { - self._intern_place_elems(ts) - } - } - pub fn intern_canonical_var_infos(self, ts: &[CanonicalVarInfo]) -> CanonicalVarInfos<'tcx> { if ts.len() == 0 { List::empty() @@ -2751,11 +2685,6 @@ impl<'tcx> TyCtxt<'tcx> { iter.intern_with(|xs| self.intern_substs(xs)) } - pub fn mk_place_elems], - &'tcx List>>>(self, iter: I) -> I::Output { - iter.intern_with(|xs| self.intern_place_elems(xs)) - } - pub fn mk_substs_trait(self, self_ty: Ty<'tcx>, rest: &[GenericArg<'tcx>]) @@ -2921,29 +2850,8 @@ impl<'a, T, R> InternIteratorElement for &'a T impl InternIteratorElement for Result { type Output = Result; - fn intern_with, F: FnOnce(&[T]) -> R>(mut iter: I, f: F) - -> Self::Output { - // This code is hot enough that it's worth specializing for the most - // common length lists, to avoid the overhead of `SmallVec` creation. - // The match arms are in order of frequency. The 1, 2, and 0 cases are - // typically hit in ~95% of cases. We assume that if the upper and - // lower bounds from `size_hint` agree they are correct. - Ok(match iter.size_hint() { - (1, Some(1)) => { - f(&[iter.next().unwrap()?]) - } - (2, Some(2)) => { - let t0 = iter.next().unwrap()?; - let t1 = iter.next().unwrap()?; - f(&[t0, t1]) - } - (0, Some(0)) => { - f(&[]) - } - _ => { - f(&iter.collect::, _>>()?) - } - }) + fn intern_with, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { + Ok(f(&iter.collect::, _>>()?)) } } @@ -3004,7 +2912,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { }; providers.extern_mod_stmt_cnum = |tcx, id| { let id = tcx.hir().as_local_node_id(id).unwrap(); - tcx.extern_crate_map.get(&id).cloned() + tcx.cstore.extern_mod_stmt_cnum_untracked(id) }; providers.all_crate_nums = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 77613b548cfdb..5851a48a8d377 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -45,12 +45,13 @@ pub enum TypeError<'tcx> { ProjectionMismatched(ExpectedFound), ProjectionBoundsLength(ExpectedFound), ExistentialMismatch(ExpectedFound<&'tcx ty::List>>), - ObjectUnsafeCoercion(DefId), + ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>), IntrinsicCast, } +#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] pub enum UnconstrainedNumeric { UnconstrainedFloat, UnconstrainedInt, @@ -178,7 +179,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { IntrinsicCast => { write!(f, "cannot coerce intrinsics to function pointers") } - ObjectUnsafeCoercion(_) => write!(f, "coercion to object-unsafe trait object"), } } } diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 27a09b394b8fa..7d6ae3f815af1 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -1,6 +1,7 @@ use crate::hir::def_id::DefId; use crate::ich::StableHashingContext; -use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; +use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, + HashStable}; use std::fmt::Debug; use std::hash::Hash; use std::mem; @@ -19,7 +20,7 @@ pub type SimplifiedType = SimplifiedTypeGen; /// the non-stable but fast to construct DefId-version is the better choice. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)] pub enum SimplifiedTypeGen - where D: Copy + Debug + Ord + Eq + where D: Copy + Debug + Ord + Eq + Hash { BoolSimplifiedType, CharSimplifiedType, @@ -123,10 +124,10 @@ pub fn simplify_type( } } -impl SimplifiedTypeGen { +impl SimplifiedTypeGen { pub fn map_def(self, map: F) -> SimplifiedTypeGen where F: Fn(D) -> U, - U: Copy + Debug + Ord + Eq, + U: Copy + Debug + Ord + Eq + Hash, { match self { BoolSimplifiedType => BoolSimplifiedType, @@ -155,9 +156,11 @@ impl SimplifiedTypeGen { impl<'a, D> HashStable> for SimplifiedTypeGen where - D: Copy + Debug + Ord + Eq + HashStable>, + D: Copy + Debug + Ord + Eq + Hash + HashStable>, { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { BoolSimplifiedType | diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index cb1fb4f685de5..6e43aa6a25d55 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -94,7 +94,7 @@ impl FlagComputation { &ty::Generator(_, ref substs, _) => { self.add_flags(TypeFlags::HAS_TY_CLOSURE); self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); - self.add_substs(substs); + self.add_substs(&substs.substs); } &ty::GeneratorWitness(ref ts) => { @@ -106,7 +106,7 @@ impl FlagComputation { &ty::Closure(_, ref substs) => { self.add_flags(TypeFlags::HAS_TY_CLOSURE); self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); - self.add_substs(substs); + self.add_substs(&substs.substs); } &ty::Bound(debruijn, _) => { @@ -240,19 +240,17 @@ impl FlagComputation { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER); match infer { InferConst::Fresh(_) => {} + InferConst::Canonical(debruijn, _) => self.add_binder(debruijn), InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX), } } - ConstValue::Bound(debruijn, _) => self.add_binder(debruijn), ConstValue::Param(_) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_PARAMS); } ConstValue::Placeholder(_) => { self.add_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_CT_PLACEHOLDER); } - ConstValue::Scalar(_) => { } - ConstValue::Slice { data: _, start: _, end: _ } => { } - ConstValue::ByRef { alloc: _, offset: _ } => { } + _ => {}, } } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index bacf3d42f0431..f6a5092d30d40 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -88,9 +88,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn has_infer_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_INFER) } - fn has_infer_consts(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_CT_INFER) - } fn has_local_value(&self) -> bool { self.has_type_flags(TypeFlags::KEEP_IN_LOCAL_TCX) } @@ -521,7 +518,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ty::Const { val: ConstValue::Bound(debruijn, bound_const), ty } = *ct { + if let ty::Const { + val: ConstValue::Infer(ty::InferConst::Canonical(debruijn, bound_const)), + ty, + } = *ct { if debruijn == self.current_index { let fld_c = &mut self.fld_c; let ct = fld_c(bound_const, ty); @@ -567,10 +567,7 @@ impl<'tcx> TyCtxt<'tcx> { // identity for bound types and consts let fld_t = |bound_ty| self.mk_ty(ty::Bound(ty::INNERMOST, bound_ty)); let fld_c = |bound_ct, ty| { - self.mk_const(ty::Const { - val: ConstValue::Bound(ty::INNERMOST, bound_ct), - ty, - }) + self.mk_const_infer(ty::InferConst::Canonical(ty::INNERMOST, bound_ct), ty) }; self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c) } @@ -721,6 +718,7 @@ impl<'tcx> TyCtxt<'tcx> { // vars. See comment on `shift_vars_through_binders` method in // `subst.rs` for more details. +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] enum Direction { In, Out, @@ -801,7 +799,10 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ty::Const { val: ConstValue::Bound(debruijn, bound_ct), ty } = *ct { + if let ty::Const { + val: ConstValue::Infer(ty::InferConst::Canonical(debruijn, bound_const)), + ty, + } = *ct { if self.amount == 0 || debruijn < self.current_index { ct } else { @@ -812,10 +813,7 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { debruijn.shifted_out(self.amount) } }; - self.tcx.mk_const(ty::Const { - val: ConstValue::Bound(debruijn, bound_ct), - ty, - }) + self.tcx.mk_const_infer(ty::InferConst::Canonical(debruijn, bound_const), ty) } } else { ct.super_fold_with(self) @@ -913,14 +911,13 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { } fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> bool { - // we don't have a `visit_infer_const` callback, so we have to - // hook in here to catch this case (annoying...), but - // otherwise we do want to remember to visit the rest of the - // const, as it has types/regions embedded in a lot of other - // places. - match ct.val { - ConstValue::Bound(debruijn, _) if debruijn >= self.outer_index => true, - _ => ct.super_visit_with(self), + if let ty::Const { + val: ConstValue::Infer(ty::InferConst::Canonical(debruijn, _)), + .. + } = *ct { + debruijn >= self.outer_index + } else { + false } } } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 5139c8085a583..741830f205cb0 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -1,4 +1,3 @@ -use crate::hir::CodegenFnAttrFlags; use crate::hir::Unsafety; use crate::hir::def::Namespace; use crate::hir::def_id::DefId; @@ -26,14 +25,6 @@ pub enum InstanceDef<'tcx> { /// `::method` where `method` receives unsizeable `self: Self`. VtableShim(DefId), - /// `fn()` pointer where the function itself cannot be turned into a pointer. - /// - /// One example in the compiler today is functions annotated with `#[track_caller]`, which - /// must have their implicit caller location argument populated for a call. Because this is a - /// required part of the function's ABI but can't be tracked as a property of the function - /// pointer, we create a single "caller location" at the site where the function is reified. - ReifyShim(DefId), - /// `::call_*` /// `DefId` is `FnTrait::call_*` FnPtrShim(DefId, Ty<'tcx>), @@ -68,7 +59,7 @@ impl<'tcx> Instance<'tcx> { // Shims currently have type FnPtr. Not sure this should remain. ty::FnPtr(_) => ty.fn_sig(tcx), ty::Closure(def_id, substs) => { - let sig = substs.as_closure().sig(def_id, tcx); + let sig = substs.closure_sig(def_id, tcx); let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); sig.map_bound(|sig| tcx.mk_fn_sig( @@ -80,7 +71,7 @@ impl<'tcx> Instance<'tcx> { )) } ty::Generator(def_id, substs, _) => { - let sig = substs.as_generator().poly_sig(def_id, tcx); + let sig = substs.poly_sig(def_id, tcx); let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); @@ -132,7 +123,6 @@ impl<'tcx> InstanceDef<'tcx> { match *self { InstanceDef::Item(def_id) | InstanceDef::VtableShim(def_id) | - InstanceDef::ReifyShim(def_id) | InstanceDef::FnPtrShim(def_id, _) | InstanceDef::Virtual(def_id, _) | InstanceDef::Intrinsic(def_id, ) | @@ -188,9 +178,6 @@ impl<'tcx> fmt::Display for Instance<'tcx> { InstanceDef::VtableShim(_) => { write!(f, " - shim(vtable)") } - InstanceDef::ReifyShim(_) => { - write!(f, " - shim(reify)") - } InstanceDef::Intrinsic(_) => { write!(f, " - intrinsic") } @@ -303,30 +290,6 @@ impl<'tcx> Instance<'tcx> { result } - pub fn resolve_for_fn_ptr( - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - def_id: DefId, - substs: SubstsRef<'tcx>, - ) -> Option> { - debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); - Instance::resolve(tcx, param_env, def_id, substs).map(|resolved| { - let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags - .contains(CodegenFnAttrFlags::TRACK_CALLER); - - match resolved.def { - InstanceDef::Item(def_id) if has_track_caller(def_id) => { - debug!(" => fn pointer created for function with #[track_caller]"); - Instance { - def: InstanceDef::ReifyShim(def_id), - substs, - } - }, - _ => resolved, - } - }) - } - pub fn resolve_for_vtable( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -352,14 +315,14 @@ impl<'tcx> Instance<'tcx> { pub fn resolve_closure( tcx: TyCtxt<'tcx>, def_id: DefId, - substs: ty::SubstsRef<'tcx>, + substs: ty::ClosureSubsts<'tcx>, requested_kind: ty::ClosureKind, ) -> Instance<'tcx> { - let actual_kind = substs.as_closure().kind(def_id, tcx); + let actual_kind = substs.closure_kind(def_id, tcx); match needs_fn_once_adapter_shim(actual_kind, requested_kind) { Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs), - _ => Instance::new(def_id, substs) + _ => Instance::new(def_id, substs.substs) } } @@ -372,7 +335,7 @@ impl<'tcx> Instance<'tcx> { pub fn fn_once_adapter_instance( tcx: TyCtxt<'tcx>, closure_did: DefId, - substs: ty::SubstsRef<'tcx>, + substs: ty::ClosureSubsts<'tcx>, ) -> Instance<'tcx> { debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, @@ -385,7 +348,7 @@ impl<'tcx> Instance<'tcx> { let self_ty = tcx.mk_closure(closure_did, substs); - let sig = substs.as_closure().sig(closure_did, tcx); + let sig = substs.closure_sig(closure_did, tcx); let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); assert_eq!(sig.inputs().len(), 1); let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]); @@ -432,7 +395,7 @@ fn resolve_associated_item<'tcx>( traits::VtableGenerator(generator_data) => { Some(Instance { def: ty::InstanceDef::Item(generator_data.generator_def_id), - substs: generator_data.substs + substs: generator_data.substs.substs }) } traits::VtableClosure(closure_data) => { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index aed9e87a168ce..3accbdf9bcbc6 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1,5 +1,5 @@ use crate::session::{self, DataTypeKind}; -use crate::ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions, subst::SubstsRef}; +use crate::ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions}; use syntax::ast::{self, Ident, IntTy, UintTy}; use syntax::attr; @@ -15,15 +15,17 @@ use std::ops::Bound; use crate::hir; use crate::ich::StableHashingContext; use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; +use crate::ty::GeneratorSubsts; use crate::ty::subst::Subst; -use rustc_index::bit_set::BitSet; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_index::vec::{IndexVec, Idx}; +use rustc_data_structures::bit_set::BitSet; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, + StableHasherResult}; pub use rustc_target::abi::*; use rustc_target::spec::{HasTargetSpec, abi::Abi as SpecAbi}; use rustc_target::abi::call::{ - ArgAttribute, ArgAttributes, ArgType, Conv, FnType, PassMode, Reg, RegKind + ArgAttribute, ArgAttributes, ArgType, Conv, FnType, IgnoreMode, PassMode, Reg, RegKind }; pub trait IntegerExt { @@ -670,10 +672,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { tcx.intern_layout(unit) } - ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, substs)?, + ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, &substs)?, ty::Closure(def_id, ref substs) => { - let tys = substs.as_closure().upvar_tys(def_id, tcx); + let tys = substs.upvar_tys(def_id, tcx); univariant(&tys.map(|ty| self.layout_of(ty)).collect::, _>>()?, &ReprOptions::default(), StructKind::AlwaysSized)? @@ -824,14 +826,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }); (present_variants.next(), present_variants.next()) }; - let present_first = match present_first { - present_first @ Some(_) => present_first, + if present_first.is_none() { // Uninhabited because it has no variants, or only absent ones. - None if def.is_enum() => return tcx.layout_raw(param_env.and(tcx.types.never)), - // if it's a struct, still compute a layout so that we can still compute the - // field offsets - None => Some(VariantIdx::new(0)), - }; + return tcx.layout_raw(param_env.and(tcx.types.never)); + } let is_struct = !def.is_enum() || // Only one variant is present. @@ -1409,12 +1407,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { &self, ty: Ty<'tcx>, def_id: hir::def_id::DefId, - substs: SubstsRef<'tcx>, + substs: &GeneratorSubsts<'tcx>, ) -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> { use SavedLocalEligibility::*; let tcx = self.tcx; - let subst_field = |ty: Ty<'tcx>| { ty.subst(tcx, substs) }; + let subst_field = |ty: Ty<'tcx>| { ty.subst(tcx, substs.substs) }; let info = tcx.generator_layout(def_id); let (ineligible_locals, assignments) = self.generator_saved_local_eligibility(&info); @@ -1422,9 +1420,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Build a prefix layout, including "promoting" all ineligible // locals as part of the prefix. We compute the layout of all of // these fields at once to get optimal packing. - let discr_index = substs.as_generator().prefix_tys(def_id, tcx).count(); + let discr_index = substs.prefix_tys(def_id, tcx).count(); // FIXME(eddyb) set the correct vaidity range for the discriminant. - let discr_layout = self.layout_of(substs.as_generator().discr_ty(tcx))?; + let discr_layout = self.layout_of(substs.discr_ty(tcx))?; let discr = match &discr_layout.abi { Abi::Scalar(s) => s.clone(), _ => bug!(), @@ -1433,7 +1431,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { .map(|local| subst_field(info.field_tys[local])) .map(|ty| tcx.mk_maybe_uninit(ty)) .map(|ty| self.layout_of(ty)); - let prefix_layouts = substs.as_generator().prefix_tys(def_id, tcx) + let prefix_layouts = substs.prefix_tys(def_id, tcx) .map(|ty| self.layout_of(ty)) .chain(iter::once(Ok(discr_layout))) .chain(promoted_layouts) @@ -2150,13 +2148,13 @@ where // Tuples, generators and closures. ty::Closure(def_id, ref substs) => { - substs.as_closure().upvar_tys(def_id, tcx).nth(i).unwrap() + substs.upvar_tys(def_id, tcx).nth(i).unwrap() } ty::Generator(def_id, ref substs, _) => { match this.variants { Variants::Single { index } => { - substs.as_generator().state_tys(def_id, tcx) + substs.state_tys(def_id, tcx) .nth(index.as_usize()).unwrap() .nth(i).unwrap() } @@ -2164,7 +2162,7 @@ where if i == discr_index { return discr_layout(discr); } - substs.as_generator().prefix_tys(def_id, tcx).nth(i).unwrap() + substs.prefix_tys(def_id, tcx).nth(i).unwrap() } } } @@ -2325,7 +2323,9 @@ where } impl<'a> HashStable> for Variants { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { use crate::ty::layout::Variants::*; mem::discriminant(self).hash_stable(hcx, hasher); @@ -2349,7 +2349,9 @@ impl<'a> HashStable> for Variants { } impl<'a> HashStable> for DiscriminantKind { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { use crate::ty::layout::DiscriminantKind::*; mem::discriminant(self).hash_stable(hcx, hasher); @@ -2370,7 +2372,9 @@ impl<'a> HashStable> for DiscriminantKind { } impl<'a> HashStable> for FieldPlacement { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { use crate::ty::layout::FieldPlacement::*; mem::discriminant(self).hash_stable(hcx, hasher); @@ -2391,13 +2395,19 @@ impl<'a> HashStable> for FieldPlacement { } impl<'a> HashStable> for VariantIdx { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher, + ) { self.as_u32().hash_stable(hcx, hasher) } } impl<'a> HashStable> for Abi { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { use crate::ty::layout::Abi::*; mem::discriminant(self).hash_stable(hcx, hasher); @@ -2422,7 +2432,9 @@ impl<'a> HashStable> for Abi { } impl<'a> HashStable> for Scalar { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let Scalar { value, ref valid_range } = *self; value.hash_stable(hcx, hasher); valid_range.start().hash_stable(hcx, hasher); @@ -2464,19 +2476,29 @@ impl_stable_hash_for!(struct crate::ty::layout::AbiAndPrefAlign { }); impl<'tcx> HashStable> for Align { - fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'tcx>, + hasher: &mut StableHasher, + ) { self.bytes().hash_stable(hcx, hasher); } } impl<'tcx> HashStable> for Size { - fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'tcx>, + hasher: &mut StableHasher, + ) { self.bytes().hash_stable(hcx, hasher); } } impl<'a, 'tcx> HashStable> for LayoutError<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { use crate::ty::layout::LayoutError::*; mem::discriminant(self).hash_stable(hcx, hasher); @@ -2700,6 +2722,14 @@ where } }; + // Store the index of the last argument. This is useful for working with + // C-compatible variadic arguments. + let last_arg_idx = if sig.inputs().is_empty() { + None + } else { + Some(sig.inputs().len() - 1) + }; + let arg_of = |ty: Ty<'tcx>, arg_idx: Option| { let is_return = arg_idx.is_none(); let mut arg = mk_arg_type(ty, arg_idx); @@ -2709,7 +2739,30 @@ where // The same is true for s390x-unknown-linux-gnu // and sparc64-unknown-linux-gnu. if is_return || rust_abi || (!win_x64_gnu && !linux_s390x && !linux_sparc64) { - arg.mode = PassMode::Ignore; + arg.mode = PassMode::Ignore(IgnoreMode::Zst); + } + } + + // If this is a C-variadic function, this is not the return value, + // and there is one or more fixed arguments; ensure that the `VaListImpl` + // is ignored as an argument. + if sig.c_variadic { + match (last_arg_idx, arg_idx) { + (Some(last_idx), Some(cur_idx)) if last_idx == cur_idx => { + let va_list_did = match cx.tcx().lang_items().va_list() { + Some(did) => did, + None => bug!("`va_list` lang item required for C-variadic functions"), + }; + match ty.kind { + ty::Adt(def, _) if def.did == va_list_did => { + // This is the "spoofed" `VaListImpl`. Set the arguments mode + // so that it will be ignored. + arg.mode = PassMode::Ignore(IgnoreMode::CVarArgs); + } + _ => (), + } + } + _ => {} } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4660e8025d48e..0e9600449f62c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -4,7 +4,7 @@ pub use self::Variance::*; pub use self::AssocItemContainer::*; pub use self::BorrowKind::*; pub use self::IntVarValue::*; -pub use self::fold::{TypeFoldable, TypeVisitor}; +pub use self::fold::TypeFoldable; use crate::hir::{map as hir_map, GlobMap, TraitMap}; use crate::hir::Node; @@ -15,7 +15,6 @@ use rustc_macros::HashStable; use crate::ich::Fingerprint; use crate::ich::StableHashingContext; use crate::infer::canonical::Canonical; -use crate::middle::cstore::CrateStoreDyn; use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use crate::middle::resolve_lifetime::ObjectLifetimeDefault; use crate::mir::Body; @@ -29,7 +28,7 @@ use crate::ty::subst::{Subst, InternalSubsts, SubstsRef}; use crate::ty::util::{IntTypeExt, Discr}; use crate::ty::walk::TypeWalker; use crate::util::captures::Captures; -use crate::util::nodemap::{NodeMap, NodeSet, DefIdMap, FxHashMap}; +use crate::util::nodemap::{NodeSet, DefIdMap, FxHashMap}; use arena::SyncDroplessArena; use crate::session::DataTypeKind; @@ -46,14 +45,15 @@ use std::{mem, ptr}; use std::ops::Range; use syntax::ast::{self, Name, Ident, NodeId}; use syntax::attr; -use syntax_expand::hygiene::ExpnId; -use syntax::symbol::{kw, sym, Symbol}; +use syntax::ext::hygiene::ExpnId; +use syntax::symbol::{kw, sym, Symbol, InternedString}; use syntax_pos::Span; use smallvec; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; -use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, + HashStable}; use crate::hir; @@ -76,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, GeneratorInteriorTypeCause, TypeckTables, CtxtInterners, GlobalCtxt}; +pub use self::context::{Lift, TypeckTables, CtxtInterners, GlobalCtxt}; pub use self::context::{ UserTypeAnnotationIndex, UserType, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, ResolvedOpaqueTy, @@ -120,10 +120,8 @@ mod sty; // Data types -pub struct ResolverOutputs { - pub definitions: hir_map::Definitions, - pub cstore: Box, - pub extern_crate_map: NodeMap, +#[derive(Clone)] +pub struct Resolutions { pub trait_map: TraitMap, pub maybe_unused_trait_imports: NodeSet, pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, @@ -161,7 +159,7 @@ impl AssocItemContainer { /// The "header" of an impl is everything outside the body: a Self type, a trait /// ref (in the case of a trait impl), and a set of predicates (from the /// bounds / where-clauses). -#[derive(Clone, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct ImplHeader<'tcx> { pub impl_def_id: DefId, pub self_ty: Ty<'tcx>, @@ -197,7 +195,7 @@ pub struct AssocItem { pub method_has_self_argument: bool, } -#[derive(Copy, Clone, PartialEq, Debug, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, RustcEncodable, RustcDecodable, HashStable)] pub enum AssocKind { Const, Method, @@ -333,7 +331,7 @@ impl Visibility { } } -#[derive(Copy, Clone, PartialEq, RustcDecodable, RustcEncodable, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Hash, HashStable)] pub enum Variance { Covariant, // T <: T iff A <: B -- e.g., function return type Invariant, // T <: T iff B == A -- e.g., type of mutable cell @@ -579,7 +577,9 @@ impl<'tcx> TyS<'tcx> { } impl<'a, 'tcx> HashStable> for ty::TyS<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let ty::TyS { ref kind, @@ -603,8 +603,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 be unsized while not requiring references to it be wide - /// pointers. + /// A dummy type used to force `List` to by unsized without requiring fat pointers. type OpaqueListContents; } @@ -703,13 +702,6 @@ impl Deref for List { type Target = [T]; #[inline(always)] fn deref(&self) -> &[T] { - self.as_ref() - } -} - -impl AsRef<[T]> for List { - #[inline(always)] - fn as_ref(&self) -> &[T] { unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) } @@ -754,7 +746,7 @@ pub struct UpvarId { pub closure_expr_id: LocalDefId, } -#[derive(Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, HashStable)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, Copy, HashStable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. ImmBorrow, @@ -851,7 +843,7 @@ impl ty::EarlyBoundRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). pub fn has_name(&self) -> bool { - self.name != kw::UnderscoreLifetime + self.name != kw::UnderscoreLifetime.as_interned_str() } } @@ -868,7 +860,7 @@ pub enum GenericParamDefKind { #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub struct GenericParamDef { - pub name: Symbol, + pub name: InternedString, pub def_id: DefId, pub index: u32, @@ -1020,12 +1012,15 @@ impl<'tcx> Generics { } /// Bounds on generics. -#[derive(Copy, Clone, Default, Debug, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Default, Debug, HashStable)] pub struct GenericPredicates<'tcx> { pub parent: Option, - pub predicates: &'tcx [(Predicate<'tcx>, Span)], + pub predicates: Vec<(Predicate<'tcx>, Span)>, } +impl<'tcx> rustc_serialize::UseSpecializedEncodable for GenericPredicates<'tcx> {} +impl<'tcx> rustc_serialize::UseSpecializedDecodable for GenericPredicates<'tcx> {} + impl<'tcx> GenericPredicates<'tcx> { pub fn instantiate( &self, @@ -1118,7 +1113,7 @@ pub enum Predicate<'tcx> { /// No direct syntax. May be thought of as `where T: FnFoo<...>` /// for some substitutions `...` and `T` being a closure type. /// Satisfied (or refuted) once we know the closure's kind. - ClosureKind(DefId, SubstsRef<'tcx>, ClosureKind), + ClosureKind(DefId, ClosureSubsts<'tcx>, ClosureKind), /// `T1 <: T2` Subtype(PolySubtypePredicate<'tcx>), @@ -1465,7 +1460,7 @@ impl<'tcx> Predicate<'tcx> { WalkTysIter::None } ty::Predicate::ClosureKind(_closure_def_id, closure_substs, _kind) => { - WalkTysIter::Types(closure_substs.types()) + WalkTysIter::Types(closure_substs.substs.types()) } ty::Predicate::ConstEvaluatable(_, substs) => { WalkTysIter::Types(substs.types()) @@ -1544,7 +1539,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } } -rustc_index::newtype_index! { +newtype_index! { /// "Universes" are used during type- and trait-checking in the /// presence of `for<..>` binders to control what sets of names are /// visible. Universes are arranged into a tree: the root universe @@ -1638,7 +1633,11 @@ impl<'a, T> HashStable> for Placeholder where T: HashStable>, { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher + ) { self.universe.hash_stable(hcx, hasher); self.name.hash_stable(hcx, hasher); } @@ -1775,7 +1774,9 @@ impl<'a, 'tcx, T> HashStable> for ParamEnvAnd<'tcx, T> where T: HashStable>, { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let ParamEnvAnd { ref param_env, ref value @@ -2009,7 +2010,9 @@ impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx AdtDef {} impl<'a> HashStable> for AdtDef { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { thread_local! { static CACHE: RefCell> = Default::default(); } @@ -2320,7 +2323,7 @@ impl<'tcx> AdtDef { } #[inline] - pub fn predicates(&self, tcx: TyCtxt<'tcx>) -> GenericPredicates<'tcx> { + pub fn predicates(&self, tcx: TyCtxt<'tcx>) -> &'tcx GenericPredicates<'tcx> { tcx.predicates_of(self.did) } @@ -2560,7 +2563,7 @@ impl<'tcx> AdtDef { def_id: sized_trait, substs: tcx.mk_substs_trait(ty, &[]) }).to_predicate(); - let predicates = tcx.predicates_of(self.did).predicates; + let predicates = &tcx.predicates_of(self.did).predicates; if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { @@ -3021,7 +3024,7 @@ impl<'tcx> TyCtxt<'tcx> { }), _ => def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| { bug!("item_name: no name for {:?}", self.def_path(id)); - }), + }).as_symbol(), } } } @@ -3033,7 +3036,6 @@ impl<'tcx> TyCtxt<'tcx> { self.optimized_mir(did) } ty::InstanceDef::VtableShim(..) | - ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::Virtual(..) | @@ -3395,129 +3397,6 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { fn_like.asyncness() } -pub enum NonStructuralMatchTy<'tcx> { - Adt(&'tcx AdtDef), - Param, -} - -/// This method traverses the structure of `ty`, trying to find an -/// instance of an ADT (i.e. struct or enum) that was declared without -/// the `#[structural_match]` attribute, or a generic type parameter -/// (which cannot be determined to be `structural_match`). -/// -/// The "structure of a type" includes all components that would be -/// considered when doing a pattern match on a constant of that -/// type. -/// -/// * This means this method descends into fields of structs/enums, -/// and also descends into the inner type `T` of `&T` and `&mut T` -/// -/// * The traversal doesn't dereference unsafe pointers (`*const T`, -/// `*mut T`), and it does not visit the type arguments of an -/// instantiated generic like `PhantomData`. -/// -/// The reason we do this search is Rust currently require all ADTs -/// reachable from a constant's type to be annotated with -/// `#[structural_match]`, an attribute which essentially says that -/// the implementation of `PartialEq::eq` behaves *equivalently* to a -/// comparison against the unfolded structure. -/// -/// For more background on why Rust has this requirement, and issues -/// that arose when the requirement was not enforced completely, see -/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307. -pub fn search_for_structural_match_violation<'tcx>( - tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>, -) -> Option> { - let mut search = Search { tcx, found: None, seen: FxHashSet::default() }; - ty.visit_with(&mut search); - return search.found; - - struct Search<'tcx> { - tcx: TyCtxt<'tcx>, - - // Records the first ADT or type parameter we find without `#[structural_match`. - found: Option>, - - // Tracks ADTs previously encountered during search, so that - // we will not recurse on them again. - seen: FxHashSet, - } - - impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - debug!("Search visiting ty: {:?}", ty); - - let (adt_def, substs) = match ty.kind { - ty::Adt(adt_def, substs) => (adt_def, substs), - ty::Param(_) => { - self.found = Some(NonStructuralMatchTy::Param); - return true; // Stop visiting. - } - ty::RawPtr(..) => { - // `#[structural_match]` ignores substructure of - // `*const _`/`*mut _`, so skip super_visit_with - // - // (But still tell caller to continue search.) - return false; - } - ty::FnDef(..) | ty::FnPtr(..) => { - // types of formals and return in `fn(_) -> _` are also irrelevant - // - // (But still tell caller to continue search.) - return false; - } - ty::Array(_, n) if n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) - => { - // rust-lang/rust#62336: ignore type of contents - // for empty array. - return false; - } - _ => { - ty.super_visit_with(self); - return false; - } - }; - - if !self.tcx.has_attr(adt_def.did, sym::structural_match) { - self.found = Some(NonStructuralMatchTy::Adt(&adt_def)); - debug!("Search found adt_def: {:?}", adt_def); - return true; // Stop visiting. - } - - if !self.seen.insert(adt_def.did) { - debug!("Search already seen adt_def: {:?}", adt_def); - // let caller continue its search - return false; - } - - // `#[structural_match]` does not care about the - // instantiation of the generics in an ADT (it - // instead looks directly at its fields outside - // this match), so we skip super_visit_with. - // - // (Must not recur on substs for `PhantomData` cf - // rust-lang/rust#55028 and rust-lang/rust#55837; but also - // want to skip substs when only uses of generic are - // behind unsafe pointers `*const T`/`*mut T`.) - - // even though we skip super_visit_with, we must recur on - // fields of ADT. - let tcx = self.tcx; - for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) { - if field_ty.visit_with(self) { - // found an ADT without `#[structural_match]`; halt visiting! - assert!(self.found.is_some()); - return true; - } - } - - // Even though we do not want to recur on substs, we do - // want our caller to continue its own search. - false - } - } -} pub fn provide(providers: &mut ty::query::Providers<'_>) { context::provide(providers); @@ -3525,7 +3404,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { layout::provide(providers); util::provide(providers); constness::provide(providers); - crate::traits::query::dropck_outlives::provide(providers); *providers = ty::query::Providers { asyncness, associated_item, @@ -3554,11 +3432,11 @@ pub struct CrateInherentImpls { pub inherent_impls: DefIdMap>, } -#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)] pub struct SymbolName { // FIXME: we don't rely on interning or equality here - better have // this be a `&'tcx str`. - pub name: Symbol + pub name: InternedString } impl_stable_hash_for!(struct self::SymbolName { @@ -3568,24 +3446,11 @@ impl_stable_hash_for!(struct self::SymbolName { impl SymbolName { pub fn new(name: &str) -> SymbolName { SymbolName { - name: Symbol::intern(name) + name: InternedString::intern(name) } } } -impl PartialOrd for SymbolName { - fn partial_cmp(&self, other: &SymbolName) -> Option { - self.name.as_str().partial_cmp(&other.name.as_str()) - } -} - -/// Ordering must use the chars to ensure reproducible builds. -impl Ord for SymbolName { - fn cmp(&self, other: &SymbolName) -> Ordering { - self.name.as_str().cmp(&other.name.as_str()) - } -} - impl fmt::Display for SymbolName { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.name, fmt) diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index 80e77cdfad0b6..9a2e30f7f45ed 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -62,14 +62,14 @@ impl<'tcx> TyCtxt<'tcx> { // projection). match ty.kind { ty::Closure(def_id, ref substs) => { - for upvar_ty in substs.as_closure().upvar_tys(def_id, *self) { + for upvar_ty in substs.upvar_tys(def_id, *self) { self.compute_components(upvar_ty, out); } } ty::Generator(def_id, ref substs, _) => { // Same as the closure case - for upvar_ty in substs.as_generator().upvar_tys(def_id, *self) { + for upvar_ty in substs.upvar_tys(def_id, *self) { self.compute_components(upvar_ty, out); } diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs index e72916de6a9c7..d7d43b8203f6f 100644 --- a/src/librustc/ty/print/obsolete.rs +++ b/src/librustc/ty/print/obsolete.rs @@ -8,7 +8,7 @@ use rustc::hir::def_id::DefId; use rustc::mir::interpret::ConstValue; use rustc::ty::subst::SubstsRef; -use rustc::ty::{self, Const, Instance, Ty, TyCtxt}; +use rustc::ty::{self, ClosureSubsts, Const, GeneratorSubsts, Instance, Ty, TyCtxt}; use rustc::{bug, hir}; use std::fmt::Write; use std::iter; @@ -154,8 +154,8 @@ impl DefPathBasedNames<'tcx> { self.push_type_name(sig.output(), output, debug); } } - ty::Generator(def_id, substs, _) - | ty::Closure(def_id, substs) => { + ty::Generator(def_id, GeneratorSubsts { ref substs }, _) + | ty::Closure(def_id, ClosureSubsts { ref substs }) => { self.push_def_path(def_id, output); let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id)); let substs = substs.truncate_to(self.tcx, generics); @@ -218,9 +218,9 @@ impl DefPathBasedNames<'tcx> { // foo::bar::ItemName:: for part in self.tcx.def_path(def_id).data { if self.omit_disambiguators { - write!(output, "{}::", part.data.as_symbol()).unwrap(); + write!(output, "{}::", part.data.as_interned_str()).unwrap(); } else { - write!(output, "{}[{}]::", part.data.as_symbol(), part.disambiguator) + write!(output, "{}[{}]::", part.data.as_interned_str(), part.disambiguator) .unwrap(); } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 8a98a5d83615f..0adb75626975f 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -14,7 +14,7 @@ use rustc_apfloat::Float; use rustc_target::spec::abi::Abi; use syntax::ast; use syntax::attr::{SignedInt, UnsignedInt}; -use syntax::symbol::{kw, Symbol}; +use syntax::symbol::{kw, InternedString}; use std::cell::Cell; use std::fmt::{self, Write as _}; @@ -384,7 +384,7 @@ pub trait PrettyPrinter<'tcx>: let reexport = self.tcx().item_children(visible_parent) .iter() .find(|child| child.res.def_id() == def_id) - .map(|child| child.ident.name); + .map(|child| child.ident.as_interned_str()); if let Some(reexport) = reexport { *name = reexport; } @@ -392,7 +392,7 @@ pub trait PrettyPrinter<'tcx>: // Re-exported `extern crate` (#43189). DefPathData::CrateRoot => { data = DefPathData::TypeNs( - self.tcx().original_crate_name(def_id.krate), + self.tcx().original_crate_name(def_id.krate).as_interned_str(), ); } _ => {} @@ -605,8 +605,8 @@ pub trait PrettyPrinter<'tcx>: } ty::Str => p!(write("str")), ty::Generator(did, substs, movability) => { - let upvar_tys = substs.as_generator().upvar_tys(did, self.tcx()); - let witness = substs.as_generator().witness(did, self.tcx()); + let upvar_tys = substs.upvar_tys(did, self.tcx()); + let witness = substs.witness(did, self.tcx()); if movability == hir::GeneratorMovability::Movable { p!(write("[generator")); } else { @@ -649,7 +649,7 @@ pub trait PrettyPrinter<'tcx>: p!(in_binder(&types)); } ty::Closure(did, substs) => { - let upvar_tys = substs.as_closure().upvar_tys(did, self.tcx()); + let upvar_tys = substs.upvar_tys(did, self.tcx()); p!(write("[closure")); // FIXME(eddyb) should use `def_span`. @@ -689,8 +689,8 @@ pub trait PrettyPrinter<'tcx>: if self.tcx().sess.verbose() { p!(write( " closure_kind_ty={:?} closure_sig_ty={:?}", - substs.as_closure().kind_ty(did, self.tcx()), - substs.as_closure().sig_ty(did, self.tcx()) + substs.closure_kind_ty(did, self.tcx()), + substs.closure_sig_ty(did, self.tcx()) )); } @@ -698,9 +698,7 @@ pub trait PrettyPrinter<'tcx>: }, ty::Array(ty, sz) => { p!(write("["), print(ty), write("; ")); - if self.tcx().sess.verbose() { - p!(write("{:?}", sz)); - } else if let ConstValue::Unevaluated(..) = sz.val { + if let ConstValue::Unevaluated(..) = sz.val { // do not try to evalute unevaluated constants. If we are const evaluating an // array length anon const, rustc will (with debug assertions) print the // constant's path. Which will end up here again. @@ -857,127 +855,126 @@ pub trait PrettyPrinter<'tcx>: ) -> Result { define_scoped_cx!(self); - if self.tcx().sess.verbose() { - p!(write("Const({:?}: {:?})", ct.val, ct.ty)); + let u8 = self.tcx().types.u8; + if let ty::FnDef(did, substs) = ct.ty.kind { + p!(print_value_path(did, substs)); return Ok(self); } - - let u8 = self.tcx().types.u8; - - match (ct.val, &ct.ty.kind) { - (_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)), - (ConstValue::Unevaluated(did, substs), _) => { - match self.tcx().def_kind(did) { - | Some(DefKind::Static) - | Some(DefKind::Const) - | Some(DefKind::AssocConst) => p!(print_value_path(did, substs)), - _ => if did.is_local() { - let span = self.tcx().def_span(did); - if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { - p!(write("{}", snip)) - } else { - p!(write("_: "), print(ct.ty)) - } + if let ConstValue::Unevaluated(did, substs) = ct.val { + match self.tcx().def_kind(did) { + | Some(DefKind::Static) + | Some(DefKind::Const) + | Some(DefKind::AssocConst) => p!(print_value_path(did, substs)), + _ => if did.is_local() { + let span = self.tcx().def_span(did); + if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { + p!(write("{}", snip)) } else { p!(write("_: "), print(ct.ty)) - }, - } - }, - (ConstValue::Infer(..), _) => p!(write("_: "), print(ct.ty)), - (ConstValue::Param(ParamConst { name, .. }), _) => p!(write("{}", name)), - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Bool) => - p!(write("{}", if data == 0 { "false" } else { "true" })), - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F32)) => - p!(write("{}f32", Single::from_bits(data))), - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F64)) => - p!(write("{}f64", Double::from_bits(data))), - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Uint(ui)) => { - let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(*ui)).size(); - let max = truncate(u128::max_value(), bit_size); - - if data == max { - p!(write("std::{}::MAX", ui)) + } } else { - p!(write("{}{}", data, ui)) - }; - }, - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => { - let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i)) - .size().bits() as u128; - let min = 1u128 << (bit_size - 1); - let max = min - 1; - - let ty = self.tcx().lift(&ct.ty).unwrap(); - let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)) - .unwrap() - .size; - match data { - d if d == min => p!(write("std::{}::MIN", i)), - d if d == max => p!(write("std::{}::MAX", i)), - _ => p!(write("{}{}", sign_extend(data, size) as i128, i)) - } - }, - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) => - p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap())), - (ConstValue::Scalar(_), ty::RawPtr(_)) => p!(write("{{pointer}}")), - (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => { - let instance = { - let alloc_map = self.tcx().alloc_map.lock(); - alloc_map.unwrap_fn(ptr.alloc_id) - }; - p!(print_value_path(instance.def_id(), instance.substs)); - }, - _ => { - let printed = if let ty::Ref(_, ref_ty, _) = ct.ty.kind { - let byte_str = match (ct.val, &ref_ty.kind) { - (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { - let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); - Some(self.tcx() - .alloc_map.lock() - .unwrap_memory(ptr.alloc_id) - .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap()) - }, - (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { - // 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)) - }, - _ => None, - }; + p!(write("_: "), print(ct.ty)) + }, + } + return Ok(self); + } + if let ConstValue::Infer(..) = ct.val { + p!(write("_: "), print(ct.ty)); + return Ok(self); + } + if let ConstValue::Param(ParamConst { name, .. }) = ct.val { + p!(write("{}", name)); + return Ok(self); + } + if let ConstValue::Scalar(Scalar::Raw { data, .. }) = ct.val { + match ct.ty.kind { + ty::Bool => { + p!(write("{}", if data == 0 { "false" } else { "true" })); + return Ok(self); + }, + ty::Float(ast::FloatTy::F32) => { + p!(write("{}f32", Single::from_bits(data))); + return Ok(self); + }, + ty::Float(ast::FloatTy::F64) => { + p!(write("{}f64", Double::from_bits(data))); + return Ok(self); + }, + ty::Uint(ui) => { + let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(ui)).size(); + let max = truncate(u128::max_value(), bit_size); - if let Some(byte_str) = byte_str { - p!(write("b\"")); - for &c in byte_str { - for e in std::ascii::escape_default(c) { - self.write_char(e as char)?; - } - } - p!(write("\"")); - true - } else if let (ConstValue::Slice { data, start, end }, ty::Str) = - (ct.val, &ref_ty.kind) - { - // 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)); - true + if data == max { + p!(write("std::{}::MAX", ui)) } else { - false + p!(write("{}{}", data, ui)) + }; + return Ok(self); + }, + ty::Int(i) =>{ + let bit_size = Integer::from_attr(&self.tcx(), SignedInt(i)) + .size().bits() as u128; + let min = 1u128 << (bit_size - 1); + let max = min - 1; + + let ty = self.tcx().lift(&ct.ty).unwrap(); + let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)) + .unwrap() + .size; + match data { + d if d == min => p!(write("std::{}::MIN", i)), + d if d == max => p!(write("std::{}::MAX", i)), + _ => p!(write("{}{}", sign_extend(data, size) as i128, i)) } - } else { - false - }; - if !printed { - // fallback - p!(write("{:?} : ", ct.val), print(ct.ty)) + return Ok(self); + }, + ty::Char => { + p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap())); + return Ok(self); } + _ => {}, } - }; + } + if let ty::Ref(_, ref_ty, _) = ct.ty.kind { + let byte_str = match (ct.val, &ref_ty.kind) { + (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { + let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); + Some(self.tcx() + .alloc_map.lock() + .unwrap_memory(ptr.alloc_id) + .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap()) + }, + (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { + // 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) => { + // 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)); + return Ok(self); + }, + _ => None, + }; + if let Some(byte_str) = byte_str { + p!(write("b\"")); + for &c in byte_str { + for e in std::ascii::escape_default(c) { + self.write_char(e as char)?; + } + } + p!(write("\"")); + return Ok(self); + } + } + p!(write("{:?} : ", ct.val), print(ct.ty)); + Ok(self) } } @@ -992,7 +989,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> { empty_path: bool, in_value: bool, - used_region_names: FxHashSet, + used_region_names: FxHashSet, region_index: usize, binder_depth: usize, @@ -1222,7 +1219,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { // FIXME(eddyb) `name` should never be empty, but it // currently is for `extern { ... }` "foreign modules". - let name = disambiguated_data.data.as_symbol().as_str(); + let name = disambiguated_data.data.as_interned_str().as_str(); if !name.is_empty() { if !self.empty_path { write!(self, "::")?; @@ -1332,16 +1329,16 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { match *region { ty::ReEarlyBound(ref data) => { - data.name != kw::Invalid && - data.name != kw::UnderscoreLifetime + data.name.as_symbol() != kw::Invalid && + data.name.as_symbol() != kw::UnderscoreLifetime } ty::ReLateBound(_, br) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { if let ty::BrNamed(_, name) = br { - if name != kw::Invalid && - name != kw::UnderscoreLifetime { + if name.as_symbol() != kw::Invalid && + name.as_symbol() != kw::UnderscoreLifetime { return true; } } @@ -1397,7 +1394,7 @@ impl FmtPrinter<'_, '_, F> { // `explain_region()` or `note_and_explain_region()`. match *region { ty::ReEarlyBound(ref data) => { - if data.name != kw::Invalid { + if data.name.as_symbol() != kw::Invalid { p!(write("{}", data.name)); return Ok(self); } @@ -1406,8 +1403,8 @@ impl FmtPrinter<'_, '_, F> { ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { if let ty::BrNamed(_, name) = br { - if name != kw::Invalid && - name != kw::UnderscoreLifetime { + if name.as_symbol() != kw::Invalid && + name.as_symbol() != kw::UnderscoreLifetime { p!(write("{}", name)); return Ok(self); } @@ -1474,16 +1471,16 @@ impl FmtPrinter<'_, 'tcx, F> { where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { - fn name_by_region_index(index: usize) -> Symbol { + fn name_by_region_index(index: usize) -> InternedString { match index { - 0 => Symbol::intern("'r"), - 1 => Symbol::intern("'s"), - i => Symbol::intern(&format!("'t{}", i-2)), + 0 => InternedString::intern("'r"), + 1 => InternedString::intern("'s"), + i => InternedString::intern(&format!("'t{}", i-2)), } } // Replace any anonymous late-bound regions with named - // variants, using new unique identifiers, so that we can + // variants, using gensym'd identifiers, so that we can // clearly differentiate between named and unnamed regions in // the output. We'll probably want to tweak this over time to // decide just how much information to give. @@ -1541,7 +1538,7 @@ impl FmtPrinter<'_, 'tcx, F> { where T: TypeFoldable<'tcx> { - struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet); + struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet); impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { match *r { diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index c1c6a655d96a9..91082c59ba05a 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -73,17 +73,6 @@ impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M { format!("processing {:?} with query `{}`", def_id, name).into() } } - - default fn cache_on_disk(_: TyCtxt<'tcx>, _: Self::Key, _: Option<&Self::Value>) -> bool { - false - } - - default fn try_load_from_disk( - _: TyCtxt<'tcx>, - _: SerializedDepNodeIndex, - ) -> Option { - bug!("QueryDescription::load_from_disk() called for an unsupported query.") - } } impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> { diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs index 391ea762a083b..a25560ff762a1 100644 --- a/src/librustc/ty/query/job.rs +++ b/src/librustc/ty/query/job.rs @@ -334,13 +334,13 @@ fn pick_query<'a, 'tcx, T, F: Fn(&T) -> (Span, Lrc>)>( let mut hcx = tcx.create_stable_hashing_context(); queries.iter().min_by_key(|v| { let (span, query) = f(v); - let mut stable_hasher = StableHasher::new(); + let mut stable_hasher = StableHasher::::new(); query.info.query.hash_stable(&mut hcx, &mut stable_hasher); // Prefer entry points which have valid spans for nicer error messages // We add an integer to the tuple ensuring that entry points // with valid spans are picked first let span_cmp = if span == DUMMY_SP { 1 } else { 0 }; - (span_cmp, stable_hasher.finish::()) + (span_cmp, stable_hasher.finish()) }).unwrap() } diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs index 0a217e9ae666d..30a3e53dddfbb 100644 --- a/src/librustc/ty/query/keys.rs +++ b/src/librustc/ty/query/keys.rs @@ -8,12 +8,14 @@ use crate::ty::subst::SubstsRef; use crate::ty::fast_reject::SimplifiedType; use crate::mir; +use std::fmt::Debug; +use std::hash::Hash; use syntax_pos::{Span, DUMMY_SP}; -use syntax_pos::symbol::Symbol; +use syntax_pos::symbol::InternedString; /// The `Key` trait controls what types can legally be used as the key /// for a query. -pub(super) trait Key { +pub(super) trait Key: Clone + Hash + Eq + Debug { /// Given an instance of this key, what crate is it referring to? /// This is used to find the provider. fn query_crate(&self) -> CrateNum; @@ -188,7 +190,7 @@ impl<'tcx> Key for traits::Environment<'tcx> { } } -impl Key for Symbol { +impl Key for InternedString { fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -199,7 +201,10 @@ impl Key for Symbol { /// Canonical query goals correspond to abstract trait operations that /// are not tied to any crate in particular. -impl<'tcx, T> Key for Canonical<'tcx, T> { +impl<'tcx, T> Key for Canonical<'tcx, T> +where + T: Debug + Hash + Clone + Eq, +{ fn query_crate(&self) -> CrateNum { LOCAL_CRATE } diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 9b15ad560b5d2..f559cde4b03cf 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -37,13 +37,13 @@ use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, AdtSizedConst use crate::ty::steal::Steal; use crate::ty::util::NeedsDrop; use crate::ty::subst::SubstsRef; -use crate::util::nodemap::{DefIdSet, DefIdMap}; -use crate::util::common::ErrorReported; +use crate::util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet}; +use crate::util::common::{ErrorReported}; use crate::util::profiling::ProfileCategory::*; use rustc_data_structures::svh::Svh; -use rustc_index::bit_set::BitSet; -use rustc_index::vec::IndexVec; +use rustc_data_structures::bit_set::BitSet; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::{FxIndexMap, FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::StableVec; use rustc_data_structures::sync::Lrc; @@ -55,6 +55,7 @@ use std::ops::Deref; use std::sync::Arc; use std::any::type_name; use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::symbol::InternedString; use syntax::attr; use syntax::ast; use syntax::feature_gate; diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 21a7cf00b283f..c20e758688959 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -15,7 +15,7 @@ use errors::Diagnostic; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::sync::{Lrc, Lock, HashMapExt, Once}; -use rustc_index::vec::{IndexVec, Idx}; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_serialize::{ Decodable, Decoder, Encodable, Encoder, SpecializedDecoder, SpecializedEncoder, UseSpecializedDecodable, UseSpecializedEncodable, opaque, @@ -882,16 +882,15 @@ where } } -impl<'a, 'tcx, E> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]> - for CacheEncoder<'a, 'tcx, E> +impl<'a, 'tcx, E> SpecializedEncoder> for CacheEncoder<'a, 'tcx, E> where E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, - predicates: &&'tcx [(ty::Predicate<'tcx>, Span)]) + predicates: &ty::GenericPredicates<'tcx>) -> Result<(), Self::Error> { - ty_codec::encode_spanned_predicates(self, predicates, + ty_codec::encode_predicates(self, predicates, |encoder| &mut encoder.predicate_shorthands) } } @@ -1076,7 +1075,7 @@ where let desc = &format!("encode_query_results for {}", ::std::any::type_name::()); - time_ext(tcx.sess.time_extended(), desc, || { + time_ext(tcx.sess.time_extended(), Some(tcx.sess), desc, || { let shards = Q::query_cache(tcx).lock_shards(); assert!(shards.iter().all(|shard| shard.active.is_empty())); for (key, entry) in shards.iter().flat_map(|shard| shard.results.iter()) { diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 41b4883793b54..d247c0f9f69f3 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -9,11 +9,12 @@ use crate::ty::query::Query; use crate::ty::query::config::{QueryConfig, QueryDescription}; use crate::ty::query::job::{QueryJob, QueryResult, QueryInfo}; +use crate::util::common::{profq_msg, ProfileQueriesMsg, QueryMsg}; + use errors::DiagnosticBuilder; use errors::Level; use errors::Diagnostic; use errors::FatalError; -use errors::Handler; use rustc_data_structures::fx::{FxHashMap}; use rustc_data_structures::sync::{Lrc, Lock}; use rustc_data_structures::sharded::Sharded; @@ -60,6 +61,33 @@ impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> { } } +// If enabled, sends a message to the profile-queries thread. +macro_rules! profq_msg { + ($tcx:expr, $msg:expr) => { + if cfg!(debug_assertions) { + if $tcx.sess.profile_queries() { + profq_msg($tcx.sess, $msg) + } + } + } +} + +// 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) => {{ + let msg = if cfg!(debug_assertions) { + if $tcx.sess.profile_queries_and_keys() { + Some(format!("{:?}", $key)) + } else { None } + } else { None }; + QueryMsg { + query: $query, + msg, + } + }} +} + /// A type representing the responsibility to execute the job in the `job` field. /// This will poison the relevant query if dropped. pub(super) struct JobOwner<'a, 'tcx, Q: QueryDescription<'tcx>> { @@ -82,7 +110,8 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { loop { let mut lock = cache.get_shard_by_value(key).lock(); if let Some(value) = lock.results.get(key) { - tcx.prof.query_cache_hit(Q::NAME); + profq_msg!(tcx, ProfileQueriesMsg::CacheHit); + tcx.sess.profiler(|p| p.record_query_hit(Q::NAME)); let result = (value.value.clone(), value.index); #[cfg(debug_assertions)] { @@ -98,7 +127,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { // in another thread has completed. Record how long we wait in the // self-profiler. #[cfg(parallel_compiler)] - tcx.prof.query_blocked_start(Q::NAME); + tcx.sess.profiler(|p| p.query_blocked_start(Q::NAME)); job.clone() }, @@ -140,7 +169,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { #[cfg(parallel_compiler)] { let result = job.r#await(tcx, span); - tcx.prof.query_blocked_end(Q::NAME); + tcx.sess.profiler(|p| p.query_blocked_end(Q::NAME)); if let Err(cycle) = result { return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle)); @@ -292,12 +321,9 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn try_print_query_stack(handler: &Handler) { + pub fn try_print_query_stack() { eprintln!("query stack during panic:"); - // Be careful reyling on global state here: this code is called from - // a panic hook, which means that the global `Handler` may be in a weird - // state if it was responsible for triggering the panic. tls::with_context_opt(|icx| { if let Some(icx) = icx { let mut current_query = icx.query.clone(); @@ -310,7 +336,7 @@ impl<'tcx> TyCtxt<'tcx> { query.info.query.name(), query.info.query.describe(icx.tcx))); diag.span = icx.tcx.sess.source_map().def_span(query.info.span).into(); - handler.force_print_diagnostic(diag); + icx.tcx.sess.diagnostic().force_print_diagnostic(diag); current_query = query.parent.clone(); i += 1; @@ -328,6 +354,13 @@ impl<'tcx> TyCtxt<'tcx> { key, span); + profq_msg!(self, + ProfileQueriesMsg::QueryBegin( + span.data(), + profq_query_msg!(Q::NAME.as_str(), self, key), + ) + ); + let job = match JobOwner::try_get(self, span, &key) { TryGetJob::NotYetStarted(job) => job, TryGetJob::Cycle(result) => return result, @@ -345,8 +378,8 @@ impl<'tcx> TyCtxt<'tcx> { } if Q::ANON { - - let prof_timer = self.prof.query_provider(Q::NAME); + profq_msg!(self, ProfileQueriesMsg::ProviderBegin); + self.sess.profiler(|p| p.start_query(Q::NAME)); let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { self.start_query(job.job.clone(), diagnostics, |tcx| { @@ -356,7 +389,8 @@ impl<'tcx> TyCtxt<'tcx> { }) }); - drop(prof_timer); + self.sess.profiler(|p| p.end_query(Q::NAME)); + profq_msg!(self, ProfileQueriesMsg::ProviderEnd); self.dep_graph.read_index(dep_node_index); @@ -413,8 +447,9 @@ impl<'tcx> TyCtxt<'tcx> { // First we try to load the result from the on-disk cache. let result = if Q::cache_on_disk(self, key.clone(), None) && self.sess.opts.debugging_opts.incremental_queries { - let _prof_timer = self.prof.incr_cache_loading(Q::NAME); + self.sess.profiler(|p| p.incremental_load_result_start(Q::NAME)); let result = Q::try_load_from_disk(self, prev_dep_node_index); + 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`. @@ -429,17 +464,22 @@ impl<'tcx> TyCtxt<'tcx> { }; let result = if let Some(result) = result { + profq_msg!(self, ProfileQueriesMsg::CacheHit); + self.sess.profiler(|p| p.record_query_hit(Q::NAME)); + result } else { // We could not load a result from the on-disk cache, so // recompute. - let _prof_timer = self.prof.query_provider(Q::NAME); + + self.sess.profiler(|p| p.start_query(Q::NAME)); // The dep-graph for this computation is already in-place. let result = self.dep_graph.with_ignore(|| { Q::compute(self, key) }); + self.sess.profiler(|p| p.end_query(Q::NAME)); result }; @@ -449,6 +489,10 @@ impl<'tcx> TyCtxt<'tcx> { self.incremental_verify_ich::(&result, dep_node, dep_node_index); } + if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) { + self.dep_graph.mark_loaded_from_cache(dep_node_index, true); + } + result } @@ -502,7 +546,8 @@ impl<'tcx> TyCtxt<'tcx> { - dep-node: {:?}", key, dep_node); - let prof_timer = self.prof.query_provider(Q::NAME); + profq_msg!(self, ProfileQueriesMsg::ProviderBegin); + self.sess.profiler(|p| p.start_query(Q::NAME)); let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { self.start_query(job.job.clone(), diagnostics, |tcx| { @@ -522,7 +567,12 @@ impl<'tcx> TyCtxt<'tcx> { }) }); - drop(prof_timer); + self.sess.profiler(|p| p.end_query(Q::NAME)); + profq_msg!(self, ProfileQueriesMsg::ProviderEnd); + + if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) { + self.dep_graph.mark_loaded_from_cache(dep_node_index, false); + } if unlikely!(!diagnostics.is_empty()) { if dep_node.kind != crate::dep_graph::DepKind::Null { @@ -564,12 +614,19 @@ impl<'tcx> TyCtxt<'tcx> { let _ = self.get_query::(DUMMY_SP, key); } else { - self.prof.query_cache_hit(Q::NAME); + profq_msg!(self, ProfileQueriesMsg::CacheHit); + self.sess.profiler(|p| p.record_query_hit(Q::NAME)); } } #[allow(dead_code)] fn force_query>(self, key: Q::Key, span: Span, dep_node: DepNode) { + profq_msg!( + self, + ProfileQueriesMsg::QueryBegin(span.data(), + profq_query_msg!(Q::NAME.as_str(), self, key)) + ); + // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. let job = match JobOwner::try_get(self, span, &key) { @@ -659,6 +716,7 @@ macro_rules! define_queries_inner { use rustc_data_structures::sharded::Sharded; use crate::{ rustc_data_structures::stable_hasher::HashStable, + rustc_data_structures::stable_hasher::StableHasherResult, rustc_data_structures::stable_hasher::StableHasher, ich::StableHashingContext }; @@ -801,7 +859,7 @@ macro_rules! define_queries_inner { } #[allow(nonstandard_style)] - #[derive(Clone, Copy)] + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum QueryName { $($name),* } @@ -819,7 +877,7 @@ macro_rules! define_queries_inner { } #[allow(nonstandard_style)] - #[derive(Clone, Debug)] + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum Query<$tcx> { $($(#[$attr])* $name($K)),* } @@ -867,7 +925,9 @@ macro_rules! define_queries_inner { } impl<'a, $tcx> HashStable> for Query<$tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { $(Query::$name(key) => key.hash_stable(hcx, hasher),)* @@ -1134,6 +1194,37 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { return false } + macro_rules! def_id { + () => { + if let Some(def_id) = dep_node.extract_def_id(tcx) { + def_id + } else { + // Return from the whole function. + return false + } + } + }; + + macro_rules! krate { + () => { (def_id!()).krate } + }; + + macro_rules! force_ex { + ($tcx:expr, $query:ident, $key:expr) => { + { + $tcx.force_query::>( + $key, + DUMMY_SP, + *dep_node + ); + } + } + }; + + macro_rules! force { + ($query:ident, $key:expr) => { force_ex!(tcx, $query, $key) } + }; + 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. @@ -1152,19 +1243,7 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { bug!("force_from_dep_node: encountered {:?}", dep_node) } - DepKind::Analysis => { - let def_id = if let Some(def_id) = dep_node.extract_def_id(tcx) { - def_id - } else { - // Return from the whole function. - return false - }; - tcx.force_query::>( - def_id.krate, - DUMMY_SP, - *dep_node - ); - } + DepKind::Analysis => { force!(analysis, krate!()); } ); true diff --git a/src/librustc/ty/query/values.rs b/src/librustc/ty/query/values.rs index f0d1639f72f59..0149f75716477 100644 --- a/src/librustc/ty/query/values.rs +++ b/src/librustc/ty/query/values.rs @@ -1,7 +1,7 @@ use crate::ty::{self, Ty, TyCtxt, AdtSizedConstraint}; use crate::ty::util::NeedsDrop; -use syntax::symbol::Symbol; +use syntax::symbol::InternedString; pub(super) trait Value<'tcx>: Sized { fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self; @@ -22,7 +22,7 @@ impl<'tcx> Value<'tcx> for Ty<'tcx> { impl<'tcx> Value<'tcx> for ty::SymbolName { fn from_cycle_error(_: TyCtxt<'tcx>) -> Self { - ty::SymbolName { name: Symbol::intern("") } + ty::SymbolName { name: InternedString::intern("") } } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 1da65f4b51d36..2af6963f7122a 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::{GenericArg, GenericArgKind, SubstsRef}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use crate::ty::error::{ExpectedFound, TypeError}; -use crate::mir::interpret::{ConstValue, get_slice_bytes}; +use crate::mir::interpret::{ConstValue, Scalar}; use std::rc::Rc; use std::iter; use rustc_target::spec::abi; @@ -442,7 +442,7 @@ pub fn super_relate_tys>( // the (anonymous) type of the same closure expression. So // all of their regions should be equated. let substs = relation.relate(&a_substs, &b_substs)?; - Ok(tcx.mk_closure(a_id, &substs)) + Ok(tcx.mk_closure(a_id, substs)) } (&ty::RawPtr(ref a_mt), &ty::RawPtr(ref b_mt)) => @@ -557,62 +557,48 @@ pub fn super_relate_consts>( x.val }; - // Currently, the values that can be unified are primitive types, - // and those that derive both `PartialEq` and `Eq`, corresponding - // to `structural_match` types. - let new_const_val = match (eagerly_eval(a), eagerly_eval(b)) { + // Currently, the values that can be unified are those that + // implement both `PartialEq` and `Eq`, corresponding to + // `structural_match` types. + // FIXME(const_generics): check for `structural_match` synthetic attribute. + match (eagerly_eval(a), eagerly_eval(b)) { (ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => { // The caller should handle these cases! bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b) } (ConstValue::Param(a_p), ConstValue::Param(b_p)) if a_p.index == b_p.index => { - return Ok(a); + Ok(a) } (ConstValue::Placeholder(p1), ConstValue::Placeholder(p2)) if p1 == p2 => { - return Ok(a); + Ok(a) } - (ConstValue::Scalar(a_val), ConstValue::Scalar(b_val)) if a.ty == b.ty => { - if a_val == b_val { - Ok(ConstValue::Scalar(a_val)) - } else if let ty::FnPtr(_) = a.ty.kind { - let alloc_map = tcx.alloc_map.lock(); - let a_instance = alloc_map.unwrap_fn(a_val.to_ptr().unwrap().alloc_id); - let b_instance = alloc_map.unwrap_fn(b_val.to_ptr().unwrap().alloc_id); - if a_instance == b_instance { - Ok(ConstValue::Scalar(a_val)) - } else { - Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) - } - } else { - Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) - } + (a_val @ ConstValue::Scalar(Scalar::Raw { .. }), b_val @ _) + if a.ty == b.ty && a_val == b_val => + { + Ok(tcx.mk_const(ty::Const { + val: a_val, + ty: a.ty, + })) } - (a_val @ ConstValue::Slice { .. }, b_val @ ConstValue::Slice { .. }) => { - let a_bytes = get_slice_bytes(&tcx, a_val); - let b_bytes = get_slice_bytes(&tcx, b_val); - if a_bytes == b_bytes { - Ok(a_val) - } else { - Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) - } - } + // FIXME(const_generics): we should either handle `Scalar::Ptr` or add a comment + // saying that we're not handling it intentionally. - // FIXME(const_generics): handle `ConstValue::ByRef`. + // FIXME(const_generics): handle `ConstValue::ByRef` and `ConstValue::Slice`. // FIXME(const_generics): this is wrong, as it is a projection (ConstValue::Unevaluated(a_def_id, a_substs), ConstValue::Unevaluated(b_def_id, b_substs)) if a_def_id == b_def_id => { - let substs = - relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; - Ok(ConstValue::Unevaluated(a_def_id, &substs)) - } - _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), - }; - new_const_val.map(|val| tcx.mk_const(ty::Const { - val, - ty: a.ty, - })) + let substs = + relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; + Ok(tcx.mk_const(ty::Const { + val: ConstValue::Unevaluated(a_def_id, &substs), + ty: a.ty, + })) + } + + _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), + } } impl<'tcx> Relate<'tcx> for &'tcx ty::List> { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 5d78d563e9a4b..42d632d120ea1 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -9,7 +9,7 @@ use crate::mir::interpret::ConstValue; use crate::ty::{self, Lift, Ty, TyCtxt, InferConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::print::{FmtPrinter, Printer}; -use rustc_index::vec::{IndexVec, Idx}; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use smallvec::SmallVec; use crate::mir::interpret; @@ -749,7 +749,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch), ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch), IntrinsicCast => IntrinsicCast, - ObjectUnsafeCoercion(ref x) => return tcx.lift(x).map(ObjectUnsafeCoercion), }) } } @@ -762,8 +761,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> { Some(ty::InstanceDef::Item(def_id)), ty::InstanceDef::VtableShim(def_id) => Some(ty::InstanceDef::VtableShim(def_id)), - ty::InstanceDef::ReifyShim(def_id) => - Some(ty::InstanceDef::ReifyShim(def_id)), ty::InstanceDef::Intrinsic(def_id) => Some(ty::InstanceDef::Intrinsic(def_id)), ty::InstanceDef::FnPtrShim(def_id, ref ty) => @@ -969,7 +966,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { def: match self.def { Item(did) => Item(did.fold_with(folder)), VtableShim(did) => VtableShim(did.fold_with(folder)), - ReifyShim(did) => ReifyShim(did.fold_with(folder)), Intrinsic(did) => Intrinsic(did.fold_with(folder)), FnPtrShim(did, ty) => FnPtrShim( did.fold_with(folder), @@ -998,7 +994,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { use crate::ty::InstanceDef::*; self.substs.visit_with(visitor) || match self.def { - Item(did) | VtableShim(did) | ReifyShim(did) | Intrinsic(did) | Virtual(did, _) => { + Item(did) | VtableShim(did) | Intrinsic(did) | Virtual(did, _) => { did.visit_with(visitor) }, FnPtrShim(did, ty) | CloneShim(did, ty) => { @@ -1219,23 +1215,16 @@ EnumTypeFoldableImpl! { } } +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> { + parent, predicates + } +} + impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with>(&self, folder: &mut F) -> Self { - // This code is hot enough that it's worth specializing for a list of - // length 0. (No other length is common enough to be worth singling - // out). - if self.len() == 0 { - self - } else { - // Don't bother interning if nothing changed, which is the common - // case. - let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); - if v[..] == self[..] { - self - } else { - folder.tcx().intern_predicates(&v) - } - } + let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); + folder.tcx().intern_predicates(&v) } fn super_visit_with>(&self, visitor: &mut V) -> bool { @@ -1351,7 +1340,6 @@ EnumTypeFoldableImpl! { (ty::error::TypeError::ExistentialMismatch)(x), (ty::error::TypeError::ConstMismatch)(x), (ty::error::TypeError::IntrinsicCast), - (ty::error::TypeError::ObjectUnsafeCoercion)(x), } } @@ -1381,23 +1369,27 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { match *self { + ConstValue::ByRef { alloc, offset } => + ConstValue::ByRef { alloc, offset }, ConstValue::Infer(ic) => ConstValue::Infer(ic.fold_with(folder)), ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)), + ConstValue::Placeholder(p) => ConstValue::Placeholder(p), + ConstValue::Scalar(a) => ConstValue::Scalar(a), + ConstValue::Slice { data, start, end } => ConstValue::Slice { data, start, end }, ConstValue::Unevaluated(did, substs) => ConstValue::Unevaluated(did, substs.fold_with(folder)), - ConstValue::ByRef { .. } | ConstValue::Bound(..) | ConstValue::Placeholder(..) - | ConstValue::Scalar(..) | ConstValue::Slice { .. } => *self, - } } fn super_visit_with>(&self, visitor: &mut V) -> bool { match *self { + ConstValue::ByRef { .. } => false, ConstValue::Infer(ic) => ic.visit_with(visitor), ConstValue::Param(p) => p.visit_with(visitor), + ConstValue::Placeholder(_) => false, + ConstValue::Scalar(_) => false, + ConstValue::Slice { .. } => false, ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor), - ConstValue::ByRef { .. } | ConstValue::Bound(..) | ConstValue::Placeholder(_) - | ConstValue::Scalar(_) | ConstValue::Slice { .. } => false, } } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 3a9994ac64c77..91479751ef41d 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -8,7 +8,7 @@ use crate::infer::canonical::Canonical; use crate::mir::interpret::ConstValue; use crate::middle::region; use polonius_engine::Atom; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use rustc_macros::HashStable; use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, GenericArg, GenericArgKind}; use crate::ty::{self, AdtDef, Discr, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFoldable}; @@ -24,7 +24,7 @@ use std::marker::PhantomData; use std::ops::Range; use rustc_target::spec::abi; use syntax::ast::{self, Ident}; -use syntax::symbol::{kw, Symbol}; +use syntax::symbol::{kw, InternedString}; use self::InferTy::*; use self::TyKind::*; @@ -55,7 +55,7 @@ pub enum BoundRegion { /// /// The `DefId` is needed to distinguish free regions in /// the event of shadowing. - BrNamed(DefId, Symbol), + BrNamed(DefId, InternedString), /// Anonymous region for the implicit env pointer parameter /// to a closure @@ -158,11 +158,11 @@ pub enum TyKind<'tcx> { /// The anonymous type of a closure. Used to represent the type of /// `|a| a`. - Closure(DefId, SubstsRef<'tcx>), + Closure(DefId, ClosureSubsts<'tcx>), /// The anonymous type of a generator. Used to represent the type of /// `|a| yield a`. - Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability), + Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), /// A type representin the types stored inside a generator. /// This should only appear in GeneratorInteriors. @@ -304,7 +304,8 @@ static_assert_size!(TyKind<'_>, 24); /// type parameters is similar, but the role of CK and CS are /// different. CK represents the "yield type" and CS represents the /// "return type" of the generator. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, + Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct ClosureSubsts<'tcx> { /// Lifetime and type parameters from the enclosing function, /// concatenated with the types of the upvars. @@ -355,7 +356,7 @@ impl<'tcx> ClosureSubsts<'tcx> { /// Returns the closure kind for this closure; may return a type /// variable during inference. To get the closure kind during /// inference, use `infcx.closure_kind(def_id, substs)`. - pub fn kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> { + pub fn closure_kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> { self.split(def_id, tcx).closure_kind_ty } @@ -363,7 +364,7 @@ impl<'tcx> ClosureSubsts<'tcx> { /// closure; may contain type variables during inference. To get /// the closure signature during inference, use /// `infcx.fn_sig(def_id)`. - pub fn sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> { + pub fn closure_sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> { self.split(def_id, tcx).closure_sig_ty } @@ -372,7 +373,7 @@ impl<'tcx> ClosureSubsts<'tcx> { /// there are no type variables. /// /// If you have an inference context, use `infcx.closure_kind()`. - pub fn kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind { + pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind { self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap() } @@ -381,8 +382,8 @@ impl<'tcx> ClosureSubsts<'tcx> { /// there are no type variables. /// /// If you have an inference context, use `infcx.closure_sig()`. - pub fn sig(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { - let ty = self.sig_ty(def_id, tcx); + pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { + let ty = self.closure_sig_ty(def_id, tcx); match ty.kind { ty::FnPtr(sig) => sig, _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.kind), @@ -391,7 +392,8 @@ impl<'tcx> ClosureSubsts<'tcx> { } /// Similar to `ClosureSubsts`; see the above documentation for more. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, + RustcEncodable, RustcDecodable, HashStable)] pub struct GeneratorSubsts<'tcx> { pub substs: SubstsRef<'tcx>, } @@ -509,7 +511,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// variant indices. #[inline] pub fn discriminants( - self, + &'tcx self, def_id: DefId, tcx: TyCtxt<'tcx>, ) -> impl Iterator)> + Captures<'tcx> { @@ -521,7 +523,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// Calls `f` with a reference to the name of the enumerator for the given /// variant `v`. #[inline] - pub fn variant_name(self, v: VariantIdx) -> Cow<'static, str> { + pub fn variant_name(&self, v: VariantIdx) -> Cow<'static, str> { match v.as_usize() { Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME), Self::RETURNED => Cow::from(Self::RETURNED_NAME), @@ -566,8 +568,8 @@ impl<'tcx> GeneratorSubsts<'tcx> { #[derive(Debug, Copy, Clone)] pub enum UpvarSubsts<'tcx> { - Closure(SubstsRef<'tcx>), - Generator(SubstsRef<'tcx>), + Closure(ClosureSubsts<'tcx>), + Generator(GeneratorSubsts<'tcx>), } impl<'tcx> UpvarSubsts<'tcx> { @@ -575,11 +577,11 @@ impl<'tcx> UpvarSubsts<'tcx> { pub fn upvar_tys( self, def_id: DefId, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, ) -> impl Iterator> + 'tcx { let upvar_kinds = match self { - UpvarSubsts::Closure(substs) => substs.as_closure().split(def_id, tcx).upvar_kinds, - UpvarSubsts::Generator(substs) => substs.as_generator().split(def_id, tcx).upvar_kinds, + UpvarSubsts::Closure(substs) => substs.split(def_id, tcx).upvar_kinds, + UpvarSubsts::Generator(substs) => substs.split(def_id, tcx).upvar_kinds, }; upvar_kinds.iter().map(|t| { if let GenericArgKind::Type(ty) = t.unpack() { @@ -1033,7 +1035,7 @@ impl<'tcx> ProjectionTy<'tcx> { } } -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct GenSig<'tcx> { pub yield_ty: Ty<'tcx>, pub return_ty: Ty<'tcx>, @@ -1121,16 +1123,16 @@ pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder>>; Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct ParamTy { pub index: u32, - pub name: Symbol, + pub name: InternedString, } impl<'tcx> ParamTy { - pub fn new(index: u32, name: Symbol) -> ParamTy { + pub fn new(index: u32, name: InternedString) -> ParamTy { ParamTy { index, name: name } } pub fn for_self() -> ParamTy { - ParamTy::new(0, kw::SelfUpper) + ParamTy::new(0, kw::SelfUpper.as_interned_str()) } pub fn for_def(def: &ty::GenericParamDef) -> ParamTy { @@ -1146,11 +1148,11 @@ impl<'tcx> ParamTy { Eq, PartialEq, Ord, PartialOrd, HashStable)] pub struct ParamConst { pub index: u32, - pub name: Symbol, + pub name: InternedString, } impl<'tcx> ParamConst { - pub fn new(index: u32, name: Symbol) -> ParamConst { + pub fn new(index: u32, name: InternedString) -> ParamConst { ParamConst { index, name } } @@ -1163,7 +1165,7 @@ impl<'tcx> ParamConst { } } -rustc_index::newtype_index! { +newtype_index! { /// A [De Bruijn index][dbi] is a standard means of representing /// regions (and perhaps later types) in a higher-ranked setting. In /// particular, imagine a type like this: @@ -1323,7 +1325,7 @@ impl<'tcx> rustc_serialize::UseSpecializedDecodable for Region<'tcx> {} pub struct EarlyBoundRegion { pub def_id: DefId, pub index: u32, - pub name: Symbol, + pub name: InternedString, } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] @@ -1347,7 +1349,7 @@ pub struct FloatVid { pub index: u32, } -rustc_index::newtype_index! { +newtype_index! { pub struct RegionVid { DEBUG_FORMAT = custom, } @@ -1374,7 +1376,7 @@ pub enum InferTy { FreshFloatTy(u32), } -rustc_index::newtype_index! { +newtype_index! { pub struct BoundVar { .. } } @@ -1387,7 +1389,7 @@ pub struct BoundTy { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum BoundTyKind { Anon, - Param(Symbol), + Param(InternedString), } impl_stable_hash_for!(struct BoundTy { var, kind }); @@ -1773,10 +1775,6 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_bool(&self) -> bool { self.kind == Bool } - /// Returns `true` if this type is a `str`. - #[inline] - pub fn is_str(&self) -> bool { self.kind == Str } - #[inline] pub fn is_param(&self, index: u32) -> bool { match self.kind { @@ -2110,8 +2108,7 @@ impl<'tcx> TyS<'tcx> { pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option> { match self.kind { TyKind::Adt(adt, _) => Some(adt.variant_range()), - TyKind::Generator(def_id, substs, _) => - Some(substs.as_generator().variant_range(def_id, tcx)), + TyKind::Generator(def_id, substs, _) => Some(substs.variant_range(def_id, tcx)), _ => None, } } @@ -2128,7 +2125,7 @@ impl<'tcx> TyS<'tcx> { match self.kind { TyKind::Adt(adt, _) => Some(adt.discriminant_for_variant(tcx, variant_index)), TyKind::Generator(def_id, substs, _) => - Some(substs.as_generator().discriminant_for_variant(def_id, tcx, variant_index)), + Some(substs.discriminant_for_variant(def_id, tcx, variant_index)), _ => None, } } @@ -2150,8 +2147,8 @@ impl<'tcx> TyS<'tcx> { Adt(_, substs) | Opaque(_, substs) => { out.extend(substs.regions()) } - Closure(_, ref substs ) | - Generator(_, ref substs, _) => { + Closure(_, ClosureSubsts { ref substs }) | + Generator(_, GeneratorSubsts { ref substs }, _) => { out.extend(substs.regions()) } Projection(ref data) | UnnormalizedProjection(ref data) => { @@ -2201,9 +2198,7 @@ impl<'tcx> TyS<'tcx> { _ => bug!("cannot convert type `{:?}` to a closure kind", self), }, - // "Bound" types appear in canonical queries when the - // closure type is not yet known - Bound(..) | Infer(_) => None, + Infer(_) => None, Error => Some(ty::ClosureKind::Fn), @@ -2303,8 +2298,8 @@ impl<'tcx> Const<'tcx> { ty: Ty<'tcx>, ) -> Option { assert_eq!(self.ty, ty); - let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size; // 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) } @@ -2371,4 +2366,6 @@ pub enum InferConst<'tcx> { Var(ConstVid<'tcx>), /// A fresh const variable. See `infer::freshen` for more details. Fresh(u32), + /// Canonicalized const variable, used only when preparing a trait query. + Canonical(DebruijnIndex, BoundVar), } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 29721979099d5..e5bee3cfbd06e 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -2,10 +2,9 @@ use crate::hir::def_id::DefId; use crate::infer::canonical::Canonical; -use crate::ty::{self, Lift, List, Ty, TyCtxt, ParamConst}; +use crate::ty::{self, Lift, List, Ty, TyCtxt, InferConst, ParamConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::mir::interpret::ConstValue; -use crate::ty::sty::{ClosureSubsts, GeneratorSubsts}; use rustc_serialize::{self, Encodable, Encoder, Decodable, Decoder}; use syntax_pos::{Span, DUMMY_SP}; @@ -184,24 +183,6 @@ pub type InternalSubsts<'tcx> = List>; pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>; impl<'a, 'tcx> InternalSubsts<'tcx> { - /// Interpret these substitutions as the substitutions of a closure type. - /// Closure substitutions have a particular structure controlled by the - /// compiler that encodes information like the signature and closure kind; - /// see `ty::ClosureSubsts` struct for more comments. - pub fn as_closure(&'a self) -> ClosureSubsts<'a> { - ClosureSubsts { - substs: self, - } - } - - /// Interpret these substitutions as the substitutions of a generator type. - /// Closure substitutions have a particular structure controlled by the - /// compiler that encodes information like the signature and generator kind; - /// see `ty::GeneratorSubsts` struct for more comments. - pub fn as_generator(&'tcx self) -> GeneratorSubsts<'tcx> { - GeneratorSubsts { substs: self } - } - /// Creates a `InternalSubsts` that maps each generic parameter to itself. pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { Self::for_item(tcx, def_id, |param, _| { @@ -234,7 +215,9 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { ty::GenericParamDefKind::Const => { tcx.mk_const(ty::Const { - val: ConstValue::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)), + val: ConstValue::Infer( + InferConst::Canonical(ty::INNERMOST, ty::BoundVar::from(param.index)) + ), ty: tcx.type_of(def_id), }).into() } @@ -400,41 +383,14 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { - // This code is hot enough that it's worth specializing for the most - // common length lists, to avoid the overhead of `SmallVec` creation. - // The match arms are in order of frequency. The 1, 2, and 0 cases are - // typically hit in 90--99.99% of cases. When folding doesn't change - // the substs, it's faster to reuse the existing substs rather than - // calling `intern_substs`. - match self.len() { - 1 => { - let param0 = self[0].fold_with(folder); - if param0 == self[0] { - self - } else { - folder.tcx().intern_substs(&[param0]) - } - } - 2 => { - let param0 = self[0].fold_with(folder); - let param1 = self[1].fold_with(folder); - if param0 == self[0] && param1 == self[1] { - self - } else { - folder.tcx().intern_substs(&[param0, param1]) - } - } - 0 => { - self - } - _ => { - let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect(); - if params[..] == self[..] { - self - } else { - folder.tcx().intern_substs(¶ms) - } - } + let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect(); + + // If folding doesn't change the substs, it's faster to avoid + // calling `mk_substs` and instead reuse the existing substs. + if params[..] == self[..] { + self + } else { + folder.tcx().intern_substs(¶ms) } } diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 49ec908231548..2bb9c258f8b67 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -8,7 +8,8 @@ use crate::ty::fold::TypeFoldable; use crate::ty::{Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, + StableHasherResult}; use rustc_macros::HashStable; /// A trait's definition with type information. @@ -193,7 +194,9 @@ pub(super) fn trait_impls_of_provider( } impl<'a> HashStable> for TraitImpls { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let TraitImpls { ref blanket_impls, ref non_blanket_impls, diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 5555dace45bfa..c4d8e452441cb 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -642,12 +642,12 @@ impl<'tcx> TyCtxt<'tcx> { /// wrapped in a binder. pub fn closure_env_ty(self, closure_def_id: DefId, - closure_substs: SubstsRef<'tcx>) + closure_substs: ty::ClosureSubsts<'tcx>) -> Option>> { let closure_ty = self.mk_closure(closure_def_id, closure_substs); let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); - let closure_kind_ty = closure_substs.as_closure().kind_ty(closure_def_id, self); + let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self); let closure_kind = closure_kind_ty.to_opt_closure_kind()?; let env_ty = match closure_kind { ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty), @@ -697,9 +697,6 @@ 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>, @@ -716,16 +713,9 @@ impl<'tcx> TyCtxt<'tcx> { } 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 - } - }; + 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.seen_opaque_tys.remove(&def_id); Some(expanded_ty) } else { @@ -745,17 +735,14 @@ impl<'tcx> TyCtxt<'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { if let ty::Opaque(def_id, substs) = t.kind { self.expand_opaque_ty(def_id, substs).unwrap_or(t) - } else if t.has_projections() { - t.super_fold_with(self) } else { - t + t.super_fold_with(self) } } } let mut visitor = OpaqueTypeExpander { seen_opaque_tys: FxHashSet::default(), - expanded_cache: FxHashMap::default(), primary_def_id: def_id, found_recursion: false, tcx: self, @@ -818,8 +805,6 @@ impl<'tcx> ty::TyS<'tcx> { /// /// (Note that this implies that if `ty` has a destructor attached, /// then `needs_drop` will definitely return `true` for `ty`.) - /// - /// Note that this method is used to check eligible types in unions. #[inline] pub fn needs_drop(&'tcx self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { tcx.needs_drop_raw(param_env.and(self)).0 @@ -1032,25 +1017,34 @@ impl<'tcx> ty::TyS<'tcx> { } fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - is_item_raw(tcx, query, lang_items::CopyTraitLangItem) + let (param_env, ty) = query.into_parts(); + 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, + param_env, + ty, + trait_def_id, + DUMMY_SP, + )) } fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - is_item_raw(tcx, query, lang_items::SizedTraitLangItem) - + let (param_env, ty) = query.into_parts(); + 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, + param_env, + ty, + trait_def_id, + DUMMY_SP, + )) } fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - is_item_raw(tcx, query, lang_items::FreezeTraitLangItem) -} - -fn is_item_raw<'tcx>( - tcx: TyCtxt<'tcx>, - query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, - item: lang_items::LangItem, -) -> bool { let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(item, None); + 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, @@ -1111,15 +1105,10 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx> ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), - // Zero-length arrays never contain anything to drop. - ty::Array(_, len) if len.try_eval_usize(tcx, param_env) == Some(0) => false, - // Structural recursion. ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty), - ty::Closure(def_id, ref substs) => { - substs.as_closure().upvar_tys(def_id, tcx).any(needs_drop) - } + ty::Closure(def_id, ref substs) => substs.upvar_tys(def_id, tcx).any(needs_drop), // Pessimistically assume that all generators will require destructors // as we don't know if a destructor is a noop or not until after the MIR diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index f5b1902e3cc8c..12f0d80cd0e1c 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -110,9 +110,11 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::Adt(_, substs) | ty::Opaque(_, substs) => { stack.extend(substs.types().rev()); } - ty::Closure(_, ref substs) - | ty::Generator(_, ref substs, _) => { - stack.extend(substs.types().rev()); + ty::Closure(_, ref substs) => { + stack.extend(substs.substs.types().rev()); + } + ty::Generator(_, ref substs, _) => { + stack.extend(substs.substs.types().rev()); } ty::GeneratorWitness(ts) => { stack.extend(ts.skip_binder().iter().cloned().rev()); diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index b50e819c956e0..020926e7c8de8 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -347,7 +347,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // anyway, except via auto trait matching (which // only inspects the upvar types). subtys.skip_current_subtree(); // subtree handled by compute_projection - for upvar_ty in substs.as_closure().upvar_tys(def_id, self.infcx.tcx) { + for upvar_ty in substs.upvar_tys(def_id, self.infcx.tcx) { self.compute(upvar_ty); } } @@ -380,21 +380,16 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // obligations that don't refer to Self and // checking those - let defer_to_coercion = - self.infcx.tcx.features().object_safe_for_dispatch; - - if !defer_to_coercion { - let cause = self.cause(traits::MiscObligation); - let component_traits = - data.auto_traits().chain(data.principal_def_id()); - self.out.extend( - component_traits.map(|did| traits::Obligation::new( - cause.clone(), - param_env, - ty::Predicate::ObjectSafe(did) - )) - ); - } + let cause = self.cause(traits::MiscObligation); + let component_traits = + data.auto_traits().chain(data.principal_def_id()); + self.out.extend( + component_traits.map(|did| traits::Obligation::new( + cause.clone(), + param_env, + ty::Predicate::ObjectSafe(did) + )) + ); } // Inference variables are the complicated case, since we don't diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 3e52a6aa50850..0f472126695e0 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -6,8 +6,11 @@ use std::cell::Cell; use std::fmt::Debug; 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::dep_graph::{DepNode}; use crate::session::Session; #[cfg(test)] @@ -23,6 +26,17 @@ pub struct ErrorReported; thread_local!(static TIME_DEPTH: Cell = Cell::new(0)); +/// Parameters to the `Dump` variant of type `ProfileQueriesMsg`. +#[derive(Clone,Debug)] +pub struct ProfQDumpParams { + /// A base path for the files we will dump. + pub path:String, + /// To ensure that the compiler waits for us to finish our dumps. + pub ack:Sender<()>, + /// Toggle dumping a log file with every `ProfileQueriesMsg`. + pub dump_profq_msg_log:bool, +} + #[allow(nonstandard_style)] #[derive(Clone, Debug, PartialEq, Eq)] pub struct QueryMsg { @@ -30,6 +44,53 @@ pub struct QueryMsg { pub msg: Option, } +/// A sequence of these messages induce a trace of query-based incremental compilation. +// FIXME(matthewhammer): Determine whether we should include cycle detection here or not. +#[derive(Clone,Debug)] +pub enum ProfileQueriesMsg { + /// Begin a timed pass. + TimeBegin(String), + /// End a timed pass. + TimeEnd, + /// Begin a task (see `dep_graph::graph::with_task`). + TaskBegin(DepNode), + /// End a task. + TaskEnd, + /// Begin a new query. + /// Cannot use `Span` because queries are sent to other thread. + QueryBegin(SpanData, QueryMsg), + /// Query is satisfied by using an already-known value for the given key. + CacheHit, + /// Query requires running a provider; providers may nest, permitting queries to nest. + ProviderBegin, + /// Query is satisfied by a provider terminating with a value. + ProviderEnd, + /// Dump a record of the queries to the given path. + Dump(ProfQDumpParams), + /// Halt the profiling/monitoring background thread. + Halt +} + +/// If enabled, send a message to the profile-queries thread. +pub fn profq_msg(sess: &Session, msg: ProfileQueriesMsg) { + if let Some(s) = sess.profile_channel.borrow().as_ref() { + s.send(msg).unwrap() + } else { + // Do nothing. + } +} + +/// Set channel for profile queries channel. +pub fn profq_set_chan(sess: &Session, s: Sender) -> bool { + let mut channel = sess.profile_channel.borrow_mut(); + if channel.is_none() { + *channel = Some(s); + true + } else { + false + } +} + /// Read the current depth of `time()` calls. This is used to /// encourage indentation across threads. pub fn time_depth() -> usize { @@ -46,10 +107,10 @@ pub fn set_time_depth(depth: usize) { pub fn time(sess: &Session, what: &str, f: F) -> T where F: FnOnce() -> T, { - time_ext(sess.time_passes(), what, f) + time_ext(sess.time_passes(), Some(sess), what, f) } -pub fn time_ext(do_it: bool, what: &str, f: F) -> T where +pub fn time_ext(do_it: bool, sess: Option<&Session>, what: &str, f: F) -> T where F: FnOnce() -> T, { if !do_it { return f(); } @@ -60,9 +121,19 @@ pub fn time_ext(do_it: bool, what: &str, f: F) -> T where r }); + if let Some(sess) = sess { + if cfg!(debug_assertions) { + profq_msg(sess, ProfileQueriesMsg::TimeBegin(what.to_string())) + } + } let start = Instant::now(); let rv = f(); let dur = start.elapsed(); + if let Some(sess) = sess { + if cfg!(debug_assertions) { + profq_msg(sess, ProfileQueriesMsg::TimeEnd) + } + } print_time_passes_entry(true, what, dur); diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs index bd02e7f5a14a1..8624856a4f55c 100644 --- a/src/librustc/util/profiling.rs +++ b/src/librustc/util/profiling.rs @@ -1,9 +1,9 @@ +use std::borrow::Cow; use std::error::Error; use std::fs; use std::mem::{self, Discriminant}; use std::path::Path; use std::process; -use std::sync::Arc; use std::thread::ThreadId; use std::u32; @@ -62,206 +62,6 @@ fn thread_id_to_u64(tid: ThreadId) -> u64 { unsafe { mem::transmute::(tid) } } - -/// A reference to the SelfProfiler. It can be cloned and sent across thread -/// boundaries at will. -#[derive(Clone)] -pub struct SelfProfilerRef { - // This field is `None` if self-profiling is disabled for the current - // compilation session. - profiler: Option>, - - // We store the filter mask directly in the reference because that doesn't - // cost anything and allows for filtering with checking if the profiler is - // actually enabled. - event_filter_mask: EventFilter, -} - -impl SelfProfilerRef { - - pub fn new(profiler: Option>) -> SelfProfilerRef { - // If there is no SelfProfiler then the filter mask is set to NONE, - // ensuring that nothing ever tries to actually access it. - let event_filter_mask = profiler - .as_ref() - .map(|p| p.event_filter_mask) - .unwrap_or(EventFilter::NONE); - - SelfProfilerRef { - profiler, - event_filter_mask, - } - } - - // This shim makes sure that calls only get executed if the filter mask - // lets them pass. It also contains some trickery to make sure that - // code is optimized for non-profiling compilation sessions, i.e. anything - // past the filter check is never inlined so it doesn't clutter the fast - // path. - #[inline(always)] - fn exec(&self, event_filter: EventFilter, f: F) -> TimingGuard<'_> - where F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a> - { - #[inline(never)] - fn cold_call(profiler_ref: &SelfProfilerRef, f: F) -> TimingGuard<'_> - where F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a> - { - let profiler = profiler_ref.profiler.as_ref().unwrap(); - f(&**profiler) - } - - if unlikely!(self.event_filter_mask.contains(event_filter)) { - cold_call(self, f) - } else { - TimingGuard::none() - } - } - - /// Start profiling a generic activity. Profiling continues until the - /// TimingGuard returned from this call is dropped. - #[inline(always)] - pub fn generic_activity(&self, event_id: &str) -> TimingGuard<'_> { - self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| { - let event_id = profiler.profiler.alloc_string(event_id); - TimingGuard::start( - profiler, - profiler.generic_activity_event_kind, - event_id - ) - }) - } - - /// Start profiling a generic activity. Profiling continues until - /// `generic_activity_end` is called. The RAII-based `generic_activity` - /// usually is the better alternative. - #[inline(always)] - pub fn generic_activity_start(&self, event_id: &str) { - self.non_guard_generic_event( - |profiler| profiler.generic_activity_event_kind, - |profiler| profiler.profiler.alloc_string(event_id), - EventFilter::GENERIC_ACTIVITIES, - TimestampKind::Start, - ); - } - - /// End profiling a generic activity that was started with - /// `generic_activity_start`. The RAII-based `generic_activity` usually is - /// the better alternative. - #[inline(always)] - pub fn generic_activity_end(&self, event_id: &str) { - self.non_guard_generic_event( - |profiler| profiler.generic_activity_event_kind, - |profiler| profiler.profiler.alloc_string(event_id), - EventFilter::GENERIC_ACTIVITIES, - TimestampKind::End, - ); - } - - /// Start profiling a query provider. Profiling continues until the - /// TimingGuard returned from this call is dropped. - #[inline(always)] - pub fn query_provider(&self, query_name: QueryName) -> TimingGuard<'_> { - self.exec(EventFilter::QUERY_PROVIDERS, |profiler| { - let event_id = SelfProfiler::get_query_name_string_id(query_name); - TimingGuard::start(profiler, profiler.query_event_kind, event_id) - }) - } - - /// Record a query in-memory cache hit. - #[inline(always)] - pub fn query_cache_hit(&self, query_name: QueryName) { - self.non_guard_query_event( - |profiler| profiler.query_cache_hit_event_kind, - query_name, - EventFilter::QUERY_CACHE_HITS, - TimestampKind::Instant, - ); - } - - /// Start profiling a query being blocked on a concurrent execution. - /// Profiling continues until `query_blocked_end` is called. - #[inline(always)] - pub fn query_blocked_start(&self, query_name: QueryName) { - self.non_guard_query_event( - |profiler| profiler.query_blocked_event_kind, - query_name, - EventFilter::QUERY_BLOCKED, - TimestampKind::Start, - ); - } - - /// End profiling a query being blocked on a concurrent execution. - #[inline(always)] - pub fn query_blocked_end(&self, query_name: QueryName) { - self.non_guard_query_event( - |profiler| profiler.query_blocked_event_kind, - query_name, - EventFilter::QUERY_BLOCKED, - TimestampKind::End, - ); - } - - /// Start profiling how long it takes to load a query result from the - /// incremental compilation on-disk cache. Profiling continues until the - /// TimingGuard returned from this call is dropped. - #[inline(always)] - pub fn incr_cache_loading(&self, query_name: QueryName) -> TimingGuard<'_> { - self.exec(EventFilter::INCR_CACHE_LOADS, |profiler| { - let event_id = SelfProfiler::get_query_name_string_id(query_name); - TimingGuard::start( - profiler, - profiler.incremental_load_result_event_kind, - event_id - ) - }) - } - - #[inline(always)] - fn non_guard_query_event( - &self, - event_kind: fn(&SelfProfiler) -> StringId, - query_name: QueryName, - event_filter: EventFilter, - timestamp_kind: TimestampKind - ) { - drop(self.exec(event_filter, |profiler| { - let event_id = SelfProfiler::get_query_name_string_id(query_name); - let thread_id = thread_id_to_u64(std::thread::current().id()); - - profiler.profiler.record_event( - event_kind(profiler), - event_id, - thread_id, - timestamp_kind, - ); - - TimingGuard::none() - })); - } - - #[inline(always)] - fn non_guard_generic_event StringId>( - &self, - event_kind: fn(&SelfProfiler) -> StringId, - event_id: F, - event_filter: EventFilter, - timestamp_kind: TimestampKind - ) { - drop(self.exec(event_filter, |profiler| { - let thread_id = thread_id_to_u64(std::thread::current().id()); - - profiler.profiler.record_event( - event_kind(profiler), - event_id(profiler), - thread_id, - timestamp_kind, - ); - - TimingGuard::none() - })); - } -} - pub struct SelfProfiler { profiler: Profiler, event_filter_mask: EventFilter, @@ -343,51 +143,103 @@ impl SelfProfiler { let id = SelfProfiler::get_query_name_string_id(query_name); self.profiler.alloc_string_with_reserved_id(id, query_name.as_str()); } -} -#[must_use] -pub struct TimingGuard<'a>(Option>); + #[inline] + pub fn start_activity( + &self, + label: impl Into>, + ) { + if self.event_filter_mask.contains(EventFilter::GENERIC_ACTIVITIES) { + self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::Start); + } + } -struct TimingGuardInternal<'a> { - raw_profiler: &'a Profiler, - event_id: StringId, - event_kind: StringId, - thread_id: u64, -} + #[inline] + pub fn end_activity( + &self, + label: impl Into>, + ) { + if self.event_filter_mask.contains(EventFilter::GENERIC_ACTIVITIES) { + self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::End); + } + } -impl<'a> TimingGuard<'a> { #[inline] - pub fn start( - profiler: &'a SelfProfiler, - event_kind: StringId, - event_id: StringId, - ) -> TimingGuard<'a> { - let thread_id = thread_id_to_u64(std::thread::current().id()); - let raw_profiler = &profiler.profiler; - raw_profiler.record_event(event_kind, event_id, thread_id, TimestampKind::Start); - - TimingGuard(Some(TimingGuardInternal { - raw_profiler, - event_kind, - event_id, - thread_id, - })) + pub fn record_query_hit(&self, query_name: QueryName) { + if self.event_filter_mask.contains(EventFilter::QUERY_CACHE_HITS) { + self.record_query(query_name, self.query_cache_hit_event_kind, TimestampKind::Instant); + } } #[inline] - pub fn none() -> TimingGuard<'a> { - TimingGuard(None) + pub fn start_query(&self, query_name: QueryName) { + if self.event_filter_mask.contains(EventFilter::QUERY_PROVIDERS) { + self.record_query(query_name, self.query_event_kind, TimestampKind::Start); + } + } + + #[inline] + pub fn end_query(&self, query_name: QueryName) { + if self.event_filter_mask.contains(EventFilter::QUERY_PROVIDERS) { + self.record_query(query_name, self.query_event_kind, TimestampKind::End); + } } -} -impl<'a> Drop for TimingGuardInternal<'a> { #[inline] - fn drop(&mut self) { - self.raw_profiler.record_event( - self.event_kind, - self.event_id, - self.thread_id, - TimestampKind::End - ); + pub fn incremental_load_result_start(&self, query_name: QueryName) { + if self.event_filter_mask.contains(EventFilter::INCR_CACHE_LOADS) { + self.record_query( + query_name, + self.incremental_load_result_event_kind, + TimestampKind::Start + ); + } + } + + #[inline] + pub fn incremental_load_result_end(&self, query_name: QueryName) { + if self.event_filter_mask.contains(EventFilter::INCR_CACHE_LOADS) { + self.record_query( + query_name, + self.incremental_load_result_event_kind, + TimestampKind::End + ); + } + } + + #[inline] + pub fn query_blocked_start(&self, query_name: QueryName) { + if self.event_filter_mask.contains(EventFilter::QUERY_BLOCKED) { + self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::Start); + } + } + + #[inline] + pub fn query_blocked_end(&self, query_name: QueryName) { + if self.event_filter_mask.contains(EventFilter::QUERY_BLOCKED) { + self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::End); + } + } + + #[inline] + fn record(&self, event_id: &str, event_kind: StringId, timestamp_kind: TimestampKind) { + let thread_id = thread_id_to_u64(std::thread::current().id()); + + let event_id = self.profiler.alloc_string(event_id); + self.profiler.record_event(event_kind, event_id, thread_id, timestamp_kind); + } + + #[inline] + fn record_query( + &self, + query_name: QueryName, + event_kind: StringId, + timestamp_kind: TimestampKind, + ) { + let dep_node_name = SelfProfiler::get_query_name_string_id(query_name); + + let thread_id = thread_id_to_u64(std::thread::current().id()); + + self.profiler.record_event(event_kind, dep_node_name, thread_id, timestamp_kind); } } diff --git a/src/librustc_apfloat/ieee.rs b/src/librustc_apfloat/ieee.rs index 4abb86a5251a5..18d968fbddd9b 100644 --- a/src/librustc_apfloat/ieee.rs +++ b/src/librustc_apfloat/ieee.rs @@ -1199,8 +1199,8 @@ impl Float for IeeeFloat { } // Handle a leading minus sign. - let minus = s.starts_with('-'); - if minus || s.starts_with('+') { + let minus = s.starts_with("-"); + if minus || s.starts_with("+") { s = &s[1..]; if s.is_empty() { return Err(ParseError("String has no digits")); diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs index 5efe4fda8ccf8..1190cea21acc3 100644 --- a/src/librustc_apfloat/lib.rs +++ b/src/librustc_apfloat/lib.rs @@ -555,13 +555,12 @@ pub trait Float fn ilogb(self) -> ExpInt; /// Returns: self * 2exp for integral exponents. - /// Equivalent to C standard library function `ldexp`. fn scalbn_r(self, exp: ExpInt, round: Round) -> Self; fn scalbn(self, exp: ExpInt) -> Self { self.scalbn_r(exp, Round::NearestTiesToEven) } - /// Equivalent to C standard library function with the same name. + /// Equivalent of C standard library function. /// /// While the C standard says exp is an unspecified value for infinity and nan, /// this returns INT_MAX for infinities, and INT_MIN for NaNs (see `ilogb`). diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml index 867bbd22cfbbb..98efa6a5804bd 100644 --- a/src/librustc_codegen_llvm/Cargo.toml +++ b/src/librustc_codegen_llvm/Cargo.toml @@ -12,3 +12,9 @@ test = false [dependencies] rustc_llvm = { path = "../librustc_llvm" } + +[features] +# This is used to convince Cargo to separately cache builds of `rustc_codegen_llvm` +# when this option is enabled or not. That way we can build two, cache two +# artifacts, and have nice speedy rebuilds. +emscripten = ["rustc_llvm/emscripten"] diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index ae5cfc4d97b59..2ca517dc3b1a7 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -264,7 +264,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { val }; match self.mode { - PassMode::Ignore => {} + PassMode::Ignore(_) => {} PassMode::Pair(..) => { OperandValue::Pair(next(), next()).store(bx, dst); } @@ -319,7 +319,9 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> { ); let llreturn_ty = match self.ret.mode { - PassMode::Ignore => cx.type_void(), + PassMode::Ignore(IgnoreMode::Zst) => cx.type_void(), + PassMode::Ignore(IgnoreMode::CVarArgs) => + bug!("`va_list` should never be a return type"), PassMode::Direct(_) | PassMode::Pair(..) => { self.ret.layout.immediate_llvm_type(cx) } @@ -337,7 +339,7 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> { } let llarg_ty = match arg.mode { - PassMode::Ignore => continue, + PassMode::Ignore(_) => continue, PassMode::Direct(_) => arg.layout.immediate_llvm_type(cx), PassMode::Pair(..) => { llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 0, true)); @@ -406,7 +408,7 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> { apply(&ArgAttributes::new(), None); } match arg.mode { - PassMode::Ignore => {} + PassMode::Ignore(_) => {} PassMode::Direct(ref attrs) | PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(cx))), PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => { @@ -453,7 +455,7 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> { apply(&ArgAttributes::new(), None); } match arg.mode { - PassMode::Ignore => {} + PassMode::Ignore(_) => {} PassMode::Direct(ref attrs) | PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(bx))), PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => { diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs index 8c60c030eacdb..5d43bf6ae28bf 100644 --- a/src/librustc_codegen_llvm/allocator.rs +++ b/src/librustc_codegen_llvm/allocator.rs @@ -3,7 +3,7 @@ use std::ffi::CString; use crate::attributes; use libc::c_uint; use rustc::ty::TyCtxt; -use syntax_expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; +use syntax::ext::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; use crate::ModuleLlvm; use crate::llvm::{self, False, True}; @@ -68,7 +68,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, - "entry\0".as_ptr().cast()); + "entry\0".as_ptr() as *const _); let llbuilder = llvm::LLVMCreateBuilderInContext(llcx); llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb); @@ -80,7 +80,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc args.as_ptr(), args.len() as c_uint, None, - "\0".as_ptr().cast()); + "\0".as_ptr() as *const _); llvm::LLVMSetTailCall(ret, True); if output.is_some() { llvm::LLVMBuildRet(llbuilder, ret); diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 6a36a4a50cbf3..33b50401b22f1 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -96,12 +96,10 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { } // Currently stack probes seem somewhat incompatible with the address - // sanitizer and thread sanitizer. With asan we're already protected from - // stack overflow anyway so we don't really need stack probes regardless. - match cx.sess().opts.debugging_opts.sanitizer { - Some(Sanitizer::Address) | - Some(Sanitizer::Thread) => return, - _ => {}, + // sanitizer. With asan we're already protected from stack overflow anyway + // so we don't really need stack probes regardless. + if let Some(Sanitizer::Address) = cx.sess().opts.debugging_opts.sanitizer { + return } // probestack doesn't play nice either with `-C profile-generate`. @@ -270,37 +268,31 @@ pub fn from_fn_attrs( // optimize based on this! false } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) { - // If a specific #[unwind] attribute is present, use that. + // If a specific #[unwind] attribute is present, use that true } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) { - // Special attribute for allocator functions, which can't unwind. + // Special attribute for allocator functions, which can't unwind false - } else { + } else if let Some(id) = id { let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - 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. + 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 + true } + } else { + // assume this can possibly unwind, avoiding the application of a + // `nounwind` attribute below. + true }); // Always annotate functions with the target-cpu they are compiled for. diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index b3be3d09f17da..a43fbb68dbaed 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -53,20 +53,20 @@ fn prepare_lto(cgcx: &CodegenContext, let symbol_filter = &|&(ref name, level): &(String, SymbolExportLevel)| { if level.is_below_threshold(export_threshold) { - Some(CString::new(name.as_str()).unwrap()) + let mut bytes = Vec::with_capacity(name.len() + 1); + bytes.extend(name.bytes()); + Some(CString::new(bytes).unwrap()) } else { None } }; let exported_symbols = cgcx.exported_symbols .as_ref().expect("needs exported symbols for LTO"); - let mut symbol_white_list = { - let _timer = cgcx.prof.generic_activity("LLVM_lto_generate_symbol_white_list"); - exported_symbols[&LOCAL_CRATE] - .iter() - .filter_map(symbol_filter) - .collect::>() - }; + let mut symbol_white_list = exported_symbols[&LOCAL_CRATE] + .iter() + .filter_map(symbol_filter) + .collect::>(); + let _timer = cgcx.profile_activity("generate_symbol_white_list_for_thinlto"); info!("{} symbols to preserve in this crate", symbol_white_list.len()); // If we're performing LTO for the entire crate graph, then for each of our @@ -95,17 +95,14 @@ fn prepare_lto(cgcx: &CodegenContext, } for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() { + let _timer = cgcx.profile_activity(format!("load: {}", path.display())); let exported_symbols = cgcx.exported_symbols .as_ref().expect("needs exported symbols for LTO"); - { - let _timer = cgcx.prof.generic_activity("LLVM_lto_generate_symbol_white_list"); - symbol_white_list.extend( - exported_symbols[&cnum] - .iter() - .filter_map(symbol_filter)); - } + symbol_white_list.extend( + exported_symbols[&cnum] + .iter() + .filter_map(symbol_filter)); - let _timer = cgcx.prof.generic_activity("LLVM_lto_load_upstream_bitcode"); let archive = ArchiveRO::open(&path).expect("wanted an rlib"); let bytecodes = archive.iter().filter_map(|child| { child.ok().and_then(|c| c.name().map(|name| (name, c))) @@ -114,7 +111,7 @@ fn prepare_lto(cgcx: &CodegenContext, info!("adding bytecode {}", name); let bc_encoded = data.data(); - let (bc, id) = time_ext(cgcx.time_passes, &format!("decode {}", name), || { + let (bc, id) = time_ext(cgcx.time_passes, None, &format!("decode {}", name), || { match DecodedBytecode::new(bc_encoded) { Ok(b) => Ok((b.bytecode(), b.identifier().to_string())), Err(e) => Err(diag_handler.fatal(&e)), @@ -192,7 +189,6 @@ fn fat_lto(cgcx: &CodegenContext, symbol_white_list: &[*const libc::c_char]) -> Result, FatalError> { - let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_build_monolithic_module"); info!("going for a fat lto"); // Sort out all our lists of incoming modules into two lists. @@ -291,9 +287,8 @@ fn fat_lto(cgcx: &CodegenContext, // save and persist everything with the original module. let mut linker = Linker::new(llmod); for (bc_decoded, name) in serialized_modules { - let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_link_module"); info!("linking {:?}", name); - time_ext(cgcx.time_passes, &format!("ll link {:?}", name), || { + time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || { let data = bc_decoded.data(); linker.add(&data).map_err(|()| { let msg = format!("failed to load bc of {:?}", name); @@ -393,7 +388,6 @@ fn thin_lto(cgcx: &CodegenContext, symbol_white_list: &[*const libc::c_char]) -> Result<(Vec>, Vec), FatalError> { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis"); unsafe { info!("going for that thin, thin LTO"); @@ -544,7 +538,7 @@ pub(crate) fn run_pass_manager(cgcx: &CodegenContext, llvm::LLVMRustAddAnalysisPasses(module.module_llvm.tm, pm, module.module_llvm.llmod()); if config.verify_llvm_ir { - let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast()); + let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); llvm::LLVMRustAddPass(pm, pass.unwrap()); } @@ -579,16 +573,16 @@ pub(crate) fn run_pass_manager(cgcx: &CodegenContext, // We always generate bitcode through ThinLTOBuffers, // which do not support anonymous globals if config.bitcode_needed() { - let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr().cast()); + let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr() as *const _); llvm::LLVMRustAddPass(pm, pass.unwrap()); } if config.verify_llvm_ir { - let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast()); + let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); llvm::LLVMRustAddPass(pm, pass.unwrap()); } - time_ext(cgcx.time_passes, "LTO passes", || + time_ext(cgcx.time_passes, None, "LTO passes", || llvm::LLVMRunPassManager(pm, module.module_llvm.llmod())); llvm::LLVMDisposePassManager(pm); @@ -607,6 +601,16 @@ impl ModuleBuffer { llvm::LLVMRustModuleBufferCreate(m) }) } + + pub fn parse<'a>( + &self, + name: &str, + cx: &'a llvm::Context, + handler: &Handler, + ) -> Result<&'a llvm::Module, FatalError> { + let name = CString::new(name).unwrap(); + parse_module(cx, &name, self.data(), handler) + } } impl ModuleBufferMethods for ModuleBuffer { @@ -719,7 +723,7 @@ pub unsafe fn optimize_thin_module( // Like with "fat" LTO, get some better optimizations if landing pads // are disabled by removing all landing pads. if cgcx.no_landing_pads { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_remove_landing_pads"); + let _timer = cgcx.profile_activity("LLVM_remove_landing_pads"); llvm::LLVMRustMarkAllFunctionsNounwind(llmod); save_temp_bitcode(&cgcx, &module, "thin-lto-after-nounwind"); } @@ -732,41 +736,26 @@ pub unsafe fn optimize_thin_module( // // You can find some more comments about these functions in the LLVM // bindings we've got (currently `PassWrapper.cpp`) - { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_rename"); - if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module"; - return Err(write::llvm_err(&diag_handler, msg)) - } - save_temp_bitcode(cgcx, &module, "thin-lto-after-rename"); + if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module"; + return Err(write::llvm_err(&diag_handler, msg)) } - - { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_resolve_weak"); - if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module"; - return Err(write::llvm_err(&diag_handler, msg)) - } - save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve"); + save_temp_bitcode(cgcx, &module, "thin-lto-after-rename"); + if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module"; + return Err(write::llvm_err(&diag_handler, msg)) } - - { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_internalize"); - if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module"; - return Err(write::llvm_err(&diag_handler, msg)) - } - save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize"); + save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve"); + if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module"; + return Err(write::llvm_err(&diag_handler, msg)) } - - { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_import"); - if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module"; - return Err(write::llvm_err(&diag_handler, msg)) - } - save_temp_bitcode(cgcx, &module, "thin-lto-after-import"); + save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize"); + if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module"; + return Err(write::llvm_err(&diag_handler, msg)) } + save_temp_bitcode(cgcx, &module, "thin-lto-after-import"); // Ok now this is a bit unfortunate. This is also something you won't // find upstream in LLVM's ThinLTO passes! This is a hack for now to @@ -797,24 +786,18 @@ pub unsafe fn optimize_thin_module( // not too much) but for now at least gets LLVM to emit valid DWARF (or // so it appears). Hopefully we can remove this once upstream bugs are // fixed in LLVM. - { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_patch_debuginfo"); - llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); - save_temp_bitcode(cgcx, &module, "thin-lto-after-patch"); - } + llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); + save_temp_bitcode(cgcx, &module, "thin-lto-after-patch"); // Alright now that we've done everything related to the ThinLTO // analysis it's time to run some optimizations! Here we use the same // `run_pass_manager` as the "fat" LTO above except that we tell it to // populate a thin-specific pass manager, which presumably LLVM treats a // little differently. - { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_optimize"); - info!("running thin lto passes over {}", module.name); - let config = cgcx.config(module.kind); - run_pass_manager(cgcx, &module, config, true); - save_temp_bitcode(cgcx, &module, "thin-lto-after-pm"); - } + info!("running thin lto passes over {}", module.name); + let config = cgcx.config(module.kind); + run_pass_manager(cgcx, &module, config, true); + save_temp_bitcode(cgcx, &module, "thin-lto-after-pm"); } Ok(module) } diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 52f3a1cbb5c30..253110dcb34c0 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -221,8 +221,8 @@ impl<'a> DiagnosticHandlers<'a> { llcx: &'a llvm::Context) -> Self { let data = Box::into_raw(Box::new((cgcx, handler))); unsafe { - llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data.cast()); - llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, data.cast()); + llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data as *mut _); + llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, data as *mut _); } DiagnosticHandlers { data, llcx } } @@ -306,8 +306,6 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext, config: &ModuleConfig) -> Result<(), FatalError> { - let _timer = cgcx.prof.generic_activity("LLVM_module_optimize"); - let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; let tm = &*module.module_llvm.tm; @@ -425,16 +423,18 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext, // Finally, run the actual optimization passes { - let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_function_passes"); + let _timer = cgcx.profile_activity("LLVM_function_passes"); time_ext(config.time_passes, + None, &format!("llvm function passes [{}]", module_name.unwrap()), || { llvm::LLVMRustRunFunctionPassManager(fpm, llmod) }); } { - let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_module_passes"); + let _timer = cgcx.profile_activity("LLVM_module_passes"); time_ext(config.time_passes, + None, &format!("llvm module passes [{}]", module_name.unwrap()), || { llvm::LLVMRunPassManager(mpm, llmod) @@ -454,7 +454,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, config: &ModuleConfig) -> Result { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen"); + let _timer = cgcx.profile_activity("codegen"); { let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; @@ -505,12 +505,12 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, if write_bc || config.emit_bc_compressed || config.embed_bitcode { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_make_bitcode"); + let _timer = cgcx.profile_activity("LLVM_make_bitcode"); let thin = ThinBuffer::new(llmod); let data = thin.data(); if write_bc { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_bitcode"); + let _timer = cgcx.profile_activity("LLVM_emit_bitcode"); if let Err(e) = fs::write(&bc_out, data) { let msg = format!("failed to write bytecode to {}: {}", bc_out.display(), e); diag_handler.err(&msg); @@ -518,13 +518,12 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, } if config.embed_bitcode { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_embed_bitcode"); + let _timer = cgcx.profile_activity("LLVM_embed_bitcode"); embed_bitcode(cgcx, llcx, llmod, Some(data)); } if config.emit_bc_compressed { - let _timer = - cgcx.prof.generic_activity("LLVM_module_codegen_emit_compressed_bitcode"); + let _timer = cgcx.profile_activity("LLVM_compress_bitcode"); let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION); let data = bytecode::encode(&module.name, data); if let Err(e) = fs::write(&dst, data) { @@ -536,10 +535,10 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, embed_bitcode(cgcx, llcx, llmod, None); } - time_ext(config.time_passes, &format!("codegen passes [{}]", module_name.unwrap()), + time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()), || -> Result<(), FatalError> { if config.emit_ir { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_ir"); + let _timer = cgcx.profile_activity("LLVM_emit_ir"); let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); let out_c = path_to_c_string(&out); @@ -586,7 +585,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, } if config.emit_asm || asm_to_obj { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_asm"); + let _timer = cgcx.profile_activity("LLVM_emit_asm"); let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); // We can't use the same module for asm and binary output, because that triggers @@ -604,13 +603,13 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, } if write_obj { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_obj"); + let _timer = cgcx.profile_activity("LLVM_emit_obj"); with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(diag_handler, tm, cpm, llmod, &obj_out, llvm::FileType::ObjectFile) })?; } else if asm_to_obj { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_asm_to_obj"); + let _timer = cgcx.profile_activity("LLVM_asm_to_obj"); let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); run_assembler(cgcx, diag_handler, &assembly, &obj_out); @@ -670,7 +669,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext, let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), - "rustc.embedded.module\0".as_ptr().cast(), + "rustc.embedded.module\0".as_ptr() as *const _, ); llvm::LLVMSetInitializer(llglobal, llconst); @@ -682,7 +681,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext, } else { ".llvmbc\0" }; - llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); + llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); llvm::LLVMSetGlobalConstant(llglobal, llvm::True); @@ -690,7 +689,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext, let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), - "rustc.embedded.cmdline\0".as_ptr().cast(), + "rustc.embedded.cmdline\0".as_ptr() as *const _, ); llvm::LLVMSetInitializer(llglobal, llconst); let section = if is_apple { @@ -698,7 +697,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext, } else { ".llvmcmd\0" }; - llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); + llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); } @@ -840,7 +839,7 @@ fn create_msvc_imps( for (imp_name, val) in globals { let imp = llvm::LLVMAddGlobal(llmod, i8p_ty, - imp_name.as_ptr().cast()); + imp_name.as_ptr() as *const _); llvm::LLVMSetInitializer(imp, consts::ptrcast(val, i8p_ty)); llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage); } diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index edd34b52eade7..5758cdbebf7d7 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -36,7 +36,7 @@ use rustc_codegen_ssa::back::write::submit_codegened_module_to_llvm; use std::ffi::CString; use std::time::Instant; -use syntax_pos::symbol::Symbol; +use syntax_pos::symbol::InternedString; use rustc::hir::CodegenFnAttrs; use crate::value::Value; @@ -105,10 +105,9 @@ pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> { pub fn compile_codegen_unit( tcx: TyCtxt<'tcx>, - cgu_name: Symbol, + cgu_name: InternedString, tx_to_llvm_workers: &std::sync::mpsc::Sender>, ) { - let prof_timer = tcx.prof.generic_activity("codegen_module"); let start_time = Instant::now(); let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); @@ -120,7 +119,6 @@ pub fn compile_codegen_unit( dep_graph::hash_result, ); let time_to_codegen = start_time.elapsed(); - drop(prof_timer); // We assume that the cost to run LLVM on a CGU is proportional to // the time we needed for codegenning it. @@ -131,7 +129,7 @@ pub fn compile_codegen_unit( fn module_codegen( tcx: TyCtxt<'_>, - cgu_name: Symbol, + cgu_name: InternedString, ) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 98be0ae44335f..71a6067fd48a1 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -52,7 +52,6 @@ const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr(); impl BackendTypes for Builder<'_, 'll, 'tcx> { type Value = as BackendTypes>::Value; - type Function = as BackendTypes>::Function; type BasicBlock = as BackendTypes>::BasicBlock; type Type = as BackendTypes>::Type; type Funclet = as BackendTypes>::Funclet; diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 08fa23f2a7c9e..35d5107842d5b 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -33,7 +33,7 @@ pub fn get_fn( assert!(!instance.substs.has_param_types()); let sig = instance.fn_sig(cx.tcx()); - if let Some(&llfn) = cx.instances.borrow().get(&instance) { + if let Some(&llfn) = cx.instances().borrow().get(&instance) { return llfn; } diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index a1a5232d58832..6fbea9646b8a9 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -2,7 +2,7 @@ //! Code that is useful in various codegen modules. -use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef, ConstantInt}; +use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef}; use crate::abi; use crate::consts; use crate::type_::Type; @@ -86,8 +86,6 @@ impl Funclet<'ll> { impl BackendTypes for CodegenCx<'ll, 'tcx> { type Value = &'ll Value; - type Function = &'ll Value; - type BasicBlock = &'ll BasicBlock; type Type = &'ll Type; type Funclet = Funclet<'ll>; @@ -245,23 +243,33 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { struct_in_context(self.llcx, elts, packed) } - fn const_to_opt_uint(&self, v: &'ll Value) -> Option { - try_as_const_integral(v).map(|v| unsafe { + fn const_to_uint(&self, v: &'ll Value) -> u64 { + unsafe { llvm::LLVMConstIntGetZExtValue(v) - }) + } + } + + fn is_const_integral(&self, v: &'ll Value) -> bool { + unsafe { + llvm::LLVMIsAConstantInt(v).is_some() + } } fn const_to_opt_u128(&self, v: &'ll Value, sign_ext: bool) -> Option { - try_as_const_integral(v).and_then(|v| unsafe { - let (mut lo, mut hi) = (0u64, 0u64); - let success = llvm::LLVMRustConstInt128Get(v, sign_ext, - &mut hi, &mut lo); - if success { - Some(hi_lo_to_u128(lo, hi)) + unsafe { + if self.is_const_integral(v) { + let (mut lo, mut hi) = (0u64, 0u64); + let success = llvm::LLVMRustConstInt128Get(v, sign_ext, + &mut hi, &mut lo); + if success { + Some(hi_lo_to_u128(lo, hi)) + } else { + None + } } else { None } - }) + } } fn scalar_to_backend( @@ -297,7 +305,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } Some(GlobalAlloc::Function(fn_instance)) => { - self.get_fn_addr(fn_instance) + self.get_fn(fn_instance) } Some(GlobalAlloc::Static(def_id)) => { assert!(self.tcx.is_static(def_id)); @@ -378,9 +386,3 @@ pub fn struct_in_context( fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 { ((hi as u128) << 64) | (lo as u128) } - -fn try_as_const_integral(v: &'ll Value) -> Option<&'ll ConstantInt> { - unsafe { - llvm::LLVMIsAConstantInt(v) - } -} diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index fd7054a5a0ada..cba5ee3260c16 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -221,7 +221,7 @@ impl CodegenCx<'ll, 'tcx> { def_id); let ty = instance.ty(self.tcx); - let sym = self.tcx.symbol_name(instance).name; + let sym = self.tcx.symbol_name(instance).name.as_symbol(); debug!("get_static: sym={} instance={:?}", sym, instance); @@ -488,7 +488,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { if let Some(section) = attrs.link_section { let section = llvm::LLVMMDStringInContext( self.llcx, - section.as_str().as_ptr().cast(), + section.as_str().as_ptr() as *const _, section.as_str().len() as c_uint, ); assert!(alloc.relocations().is_empty()); @@ -500,14 +500,14 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { 0..alloc.len()); let alloc = llvm::LLVMMDStringInContext( self.llcx, - bytes.as_ptr().cast(), + bytes.as_ptr() as *const _, bytes.len() as c_uint, ); let data = [section, alloc]; let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2); llvm::LLVMAddNamedMetadataOperand( self.llmod, - "wasm.custom_sections\0".as_ptr().cast(), + "wasm.custom_sections\0".as_ptr() as *const _, meta, ); } diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 2da9387717214..58ce97039099e 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -20,6 +20,7 @@ use rustc::ty::layout::{ use rustc::ty::{self, Ty, TyCtxt, Instance}; use rustc::util::nodemap::FxHashMap; use rustc_target::spec::{HasTargetSpec, Target}; +use rustc_codegen_ssa::callee::resolve_and_get_fn; use rustc_codegen_ssa::base::wants_msvc_seh; use crate::callee::get_fn; @@ -210,7 +211,7 @@ pub unsafe fn create_module( // If skipping the PLT is enabled, we need to add some module metadata // to ensure intrinsic calls don't use it. if !sess.needs_plt() { - let avoid_plt = "RtLibUseGOT\0".as_ptr().cast(); + let avoid_plt = "RtLibUseGOT\0".as_ptr() as *const _; llvm::LLVMRustAddModuleFlag(llmod, avoid_plt, 1); } @@ -326,11 +327,11 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { &self.vtables } - fn get_fn(&self, instance: Instance<'tcx>) -> &'ll Value { - get_fn(self, instance) + fn instances(&self) -> &RefCell, &'ll Value>> { + &self.instances } - fn get_fn_addr(&self, instance: Instance<'tcx>) -> &'ll Value { + fn get_fn(&self, instance: Instance<'tcx>) -> &'ll Value { get_fn(self, instance) } @@ -361,14 +362,7 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { let tcx = self.tcx; let llfn = match tcx.lang_items().eh_personality() { Some(def_id) if !wants_msvc_seh(self.sess()) => { - self.get_fn_addr( - ty::Instance::resolve( - tcx, - ty::ParamEnv::reveal_all(), - def_id, - tcx.intern_substs(&[]), - ).unwrap() - ) + resolve_and_get_fn(self, def_id, tcx.intern_substs(&[])) } _ => { let name = if wants_msvc_seh(self.sess()) { @@ -396,14 +390,7 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { let tcx = self.tcx; assert!(self.sess().target.target.options.custom_unwind_resume); if let Some(def_id) = tcx.lang_items().eh_unwind_resume() { - let llfn = self.get_fn_addr( - ty::Instance::resolve( - tcx, - ty::ParamEnv::reveal_all(), - def_id, - tcx.intern_substs(&[]), - ).unwrap() - ); + let llfn = resolve_and_get_fn(self, def_id, tcx.intern_substs(&[])); unwresume.set(Some(llfn)); return llfn; } @@ -550,7 +537,6 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.trap", fn() -> void); ifn!("llvm.debugtrap", fn() -> void); ifn!("llvm.frameaddress", fn(t_i32) -> i8p); - ifn!("llvm.sideeffect", fn() -> void); ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32); ifn!("llvm.powi.v2f32", fn(t_v2f32, t_i32) -> t_v2f32); diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs index bdb7467a1010c..8b3ed5b0c623a 100644 --- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs +++ b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs @@ -11,8 +11,8 @@ use libc::c_uint; use syntax_pos::Pos; -use rustc_index::bit_set::BitSet; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::bit_set::BitSet; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use syntax_pos::BytePos; diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs index 9ed1c1730a697..04c9e93c7a527 100644 --- a/src/librustc_codegen_llvm/debuginfo/gdb.rs +++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs @@ -37,7 +37,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) let section_var = unsafe { llvm::LLVMGetNamedGlobal(cx.llmod, - c_section_var_name.as_ptr().cast()) + c_section_var_name.as_ptr() as *const _) }; section_var.unwrap_or_else(|| { @@ -52,7 +52,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) llvm_type).unwrap_or_else(||{ bug!("symbol `{}` is already defined", section_var_name) }); - llvm::LLVMSetSection(section_var, section_name.as_ptr().cast()); + llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _); llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents)); llvm::LLVMSetGlobalConstant(section_var, llvm::True); llvm::LLVMSetUnnamedAddr(section_var, llvm::True); diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index f0148a21ae670..1696e56c01eff 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -6,7 +6,7 @@ use super::utils::{debug_context, DIB, span_start, get_namespace_for_item, create_DIArray, is_node_local_to_unit}; use super::namespace::mangled_name_of_instance; use super::type_names::compute_debuginfo_type_name; -use super::CrateDebugContext; +use super::{CrateDebugContext}; use crate::abi; use crate::value::Value; use rustc_codegen_ssa::traits::*; @@ -30,7 +30,7 @@ use rustc::ty::Instance; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc::ty::layout::{self, Align, Integer, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx}; -use rustc::ty::subst::{GenericArgKind, SubstsRef}; +use rustc::ty::subst::GenericArgKind; use rustc::session::config::{self, DebugInfo}; use rustc::util::nodemap::FxHashMap; use rustc_fs_util::path_to_c_string; @@ -46,7 +46,7 @@ use std::iter; use std::ptr; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::symbol::{Interner, Symbol}; +use syntax::symbol::{Interner, InternedString}; use syntax_pos::{self, Span, FileName}; impl PartialEq for llvm::Metadata { @@ -187,7 +187,7 @@ impl TypeMap<'ll, 'tcx> { // The hasher we are using to generate the UniqueTypeId. We want // something that provides more than the 64 bits of the DefaultHasher. - let mut hasher = StableHasher::new(); + let mut hasher = StableHasher::::new(); let mut hcx = cx.tcx.create_stable_hashing_context(); let type_ = cx.tcx.erase_regions(&type_); hcx.while_hashing_spans(false, |hcx| { @@ -195,7 +195,7 @@ impl TypeMap<'ll, 'tcx> { type_.hash_stable(hcx, &mut hasher); }); }); - let unique_type_id = hasher.finish::().to_hex(); + let unique_type_id = hasher.finish().to_hex(); let key = self.unique_id_interner.intern(&unique_type_id); self.type_to_unique_id.insert(type_, UniqueTypeId(key)); @@ -682,7 +682,7 @@ pub fn type_metadata( } ty::Closure(def_id, substs) => { - let upvar_tys : Vec<_> = substs.as_closure().upvar_tys(def_id, cx.tcx).collect(); + let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx).collect(); let containing_scope = get_namespace_for_item(cx, def_id); prepare_tuple_metadata(cx, t, @@ -692,10 +692,9 @@ pub fn type_metadata( Some(containing_scope)).finalize(cx) } ty::Generator(def_id, substs, _) => { - let upvar_tys : Vec<_> = substs - .as_generator().prefix_tys(def_id, cx.tcx).map(|t| { - cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t) - }).collect(); + let upvar_tys : Vec<_> = substs.prefix_tys(def_id, cx.tcx).map(|t| { + cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t) + }).collect(); prepare_enum_metadata(cx, t, def_id, @@ -961,9 +960,9 @@ pub fn compile_unit_metadata( file_metadata, producer.as_ptr(), tcx.sess.opts.optimize != config::OptLevel::No, - flags.as_ptr().cast(), + flags.as_ptr() as *const _, 0, - split_name.as_ptr().cast(), + split_name.as_ptr() as *const _, kind); if tcx.sess.opts.debugging_opts.profile { @@ -992,7 +991,7 @@ pub fn compile_unit_metadata( if tcx.sess.opts.target_triple.triple().starts_with("wasm32") { let name_metadata = llvm::LLVMMDStringInContext( debug_context.llcontext, - rustc_producer.as_ptr().cast(), + rustc_producer.as_ptr() as *const _, rustc_producer.as_bytes().len() as c_uint, ); llvm::LLVMAddNamedMetadataOperand( @@ -1339,7 +1338,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]), ty::Generator(def_id, substs, _) => { let generator_layout = cx.tcx.generator_layout(*def_id); - VariantInfo::Generator(substs, generator_layout, index) + VariantInfo::Generator(*substs, generator_layout, index) } _ => bug!(), } @@ -1612,7 +1611,7 @@ enum EnumDiscriminantInfo<'ll> { #[derive(Copy, Clone)] enum VariantInfo<'tcx> { Adt(&'tcx ty::VariantDef), - Generator(SubstsRef<'tcx>, &'tcx GeneratorLayout<'tcx>, VariantIdx), + Generator(ty::GeneratorSubsts<'tcx>, &'tcx GeneratorLayout<'tcx>, VariantIdx), } impl<'tcx> VariantInfo<'tcx> { @@ -1620,7 +1619,7 @@ impl<'tcx> VariantInfo<'tcx> { match self { VariantInfo::Adt(variant) => f(&variant.ident.as_str()), VariantInfo::Generator(substs, _, variant_index) => - f(&substs.as_generator().variant_name(*variant_index)), + f(&substs.variant_name(*variant_index)), } } @@ -1764,10 +1763,9 @@ fn prepare_enum_metadata( }) .collect(), ty::Generator(_, substs, _) => substs - .as_generator() .variant_range(enum_def_id, cx.tcx) .map(|variant_index| { - let name = SmallCStr::new(&substs.as_generator().variant_name(variant_index)); + let name = SmallCStr::new(&substs.variant_name(variant_index)); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), @@ -2069,9 +2067,11 @@ fn set_members_of_composite_type(cx: &CodegenCx<'ll, 'tcx>, { let mut composite_types_completed = debug_context(cx).composite_types_completed.borrow_mut(); - if !composite_types_completed.insert(&composite_type_metadata) { + if composite_types_completed.contains(&composite_type_metadata) { bug!("debuginfo::set_members_of_composite_type() - \ Already completed forward declaration re-encountered."); + } else { + composite_types_completed.insert(composite_type_metadata); } } @@ -2125,7 +2125,7 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&' fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) - -> Vec { + -> Vec { let mut names = generics.parent.map_or(vec![], |def_id| { get_parameter_names(cx, cx.tcx.generics_of(def_id)) }); diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 5b59f4c28de20..4efa1993d4322 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -26,7 +26,7 @@ use rustc::mir; use rustc::session::config::{self, DebugInfo}; use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet}; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, MirDebugScope, VariableAccess, VariableKind, FunctionDebugContextData, type_names}; @@ -36,7 +36,7 @@ use std::ffi::{CStr, CString}; use syntax_pos::{self, Span, Pos}; use syntax::ast; -use syntax::symbol::Symbol; +use syntax::symbol::InternedString; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt}; use rustc_codegen_ssa::traits::*; @@ -127,20 +127,20 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { if cx.sess().target.target.options.is_like_osx || cx.sess().target.target.options.is_like_android { llvm::LLVMRustAddModuleFlag(cx.llmod, - "Dwarf Version\0".as_ptr().cast(), + "Dwarf Version\0".as_ptr() as *const _, 2) } // Indicate that we want CodeView debug information on MSVC if cx.sess().target.target.options.is_like_msvc { llvm::LLVMRustAddModuleFlag(cx.llmod, - "CodeView\0".as_ptr().cast(), + "CodeView\0".as_ptr() as *const _, 1) } // Prevent bitcode readers from deleting the debug info. let ptr = "Debug Info Version\0".as_ptr(); - llvm::LLVMRustAddModuleFlag(cx.llmod, ptr.cast(), + llvm::LLVMRustAddModuleFlag(cx.llmod, ptr as *const _, llvm::LLVMRustDebugMetadataVersion()); }; } @@ -490,7 +490,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) - -> Vec { + -> Vec { let mut names = generics.parent.map_or(vec![], |def_id| { get_parameter_names(cx, cx.tcx.generics_of(def_id)) }); diff --git a/src/librustc_codegen_llvm/debuginfo/namespace.rs b/src/librustc_codegen_llvm/debuginfo/namespace.rs index 628d1372b5702..889984749fdf7 100644 --- a/src/librustc_codegen_llvm/debuginfo/namespace.rs +++ b/src/librustc_codegen_llvm/debuginfo/namespace.rs @@ -35,7 +35,7 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { let namespace_name = match def_key.disambiguated_data.data { DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate).as_str(), - data => data.as_symbol().as_str() + data => data.as_interned_str().as_str() }; let namespace_name = SmallCStr::new(&namespace_name); diff --git a/src/librustc_codegen_llvm/error_codes.rs b/src/librustc_codegen_llvm/error_codes.rs new file mode 100644 index 0000000000000..042e51ed2ba7a --- /dev/null +++ b/src/librustc_codegen_llvm/error_codes.rs @@ -0,0 +1,38 @@ +register_diagnostics! { + +E0511: r##" +Invalid monomorphization of an intrinsic function was used. Erroneous code +example: + +```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail) +#![feature(platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_add(a: T, b: T) -> T; +} + +fn main() { + unsafe { simd_add(0, 1); } + // error: invalid monomorphization of `simd_add` intrinsic +} +``` + +The generic type has to be a SIMD type. Example: + +``` +#![feature(repr_simd)] +#![feature(platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +struct i32x2(i32, i32); + +extern "platform-intrinsic" { + fn simd_add(a: T, b: T) -> T; +} + +unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok! +``` +"##, + +} diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 3df8d4c26903b..b7a410c3760cd 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -20,9 +20,9 @@ use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc::hir; use syntax::ast::{self, FloatTy}; -use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::traits::*; +use rustc::session::Session; use syntax_pos::Span; use std::cmp::Ordering; @@ -724,13 +724,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { self.call(expect, &[cond, self.const_bool(expected)], None) } - fn sideeffect(&mut self) { - if self.tcx.sess.opts.debugging_opts.insert_sideeffect { - let fnname = self.get_intrinsic(&("llvm.sideeffect")); - self.call(fnname, &[], None); - } - } - fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value { let intrinsic = self.cx().get_intrinsic("llvm.va_start"); self.call(intrinsic, &[va_list], None) @@ -817,7 +810,6 @@ fn codegen_msvc_try( ) { let llfn = get_rust_try_fn(bx, &mut |mut bx| { bx.set_personality_fn(bx.eh_personality()); - bx.sideeffect(); let mut normal = bx.build_sibling_block("normal"); let mut catchswitch = bx.build_sibling_block("catchswitch"); @@ -941,8 +933,6 @@ fn codegen_gnu_try( // expected to be `*mut *mut u8` for this to actually work, but that's // managed by the standard library. - bx.sideeffect(); - let mut then = bx.build_sibling_block("then"); let mut catch = bx.build_sibling_block("catch"); @@ -1026,6 +1016,10 @@ fn get_rust_try_fn<'ll, 'tcx>( rust_try } +fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) { + span_err!(a, b, E0511, "{}", c); +} + fn generic_simd_intrinsic( bx: &mut Builder<'a, 'll, 'tcx>, name: &str, diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index e09b600afd4e5..2a63011c2f545 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -19,6 +19,7 @@ #![feature(link_args)] #![feature(static_nobundle)] #![feature(trusted_len)] +#![feature(mem_take)] use back::write::{create_target_machine, create_informational_target_machine}; use syntax_pos::symbol::Symbol; @@ -30,7 +31,6 @@ extern crate libc; #[macro_use] extern crate rustc; extern crate rustc_target; #[macro_use] extern crate rustc_data_structures; -extern crate rustc_index; extern crate rustc_incremental; extern crate rustc_codegen_utils; extern crate rustc_codegen_ssa; @@ -38,8 +38,7 @@ extern crate rustc_fs_util; extern crate rustc_driver as _; #[macro_use] extern crate log; -extern crate syntax; -extern crate syntax_expand; +#[macro_use] extern crate syntax; extern crate syntax_pos; extern crate rustc_errors as errors; @@ -49,14 +48,15 @@ use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinModul use rustc_codegen_ssa::CompiledModule; use errors::{FatalError, Handler}; use rustc::dep_graph::WorkProduct; -use syntax_expand::allocator::AllocatorKind; +use syntax::ext::allocator::AllocatorKind; +use syntax_pos::symbol::InternedString; pub use llvm_util::target_features; use std::any::Any; use std::sync::Arc; use std::ffi::CStr; use rustc::dep_graph::DepGraph; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; use rustc::session::Session; use rustc::session::config::{OutputFilenames, OutputType, PrintRequest, OptLevel}; use rustc::ty::{self, TyCtxt}; @@ -64,6 +64,8 @@ use rustc::util::common::ErrorReported; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_utils::codegen_backend::CodegenBackend; +mod error_codes; + mod back { pub mod archive; pub mod bytecode; @@ -122,7 +124,7 @@ impl ExtraBackendMethods for LlvmCodegenBackend { } fn compile_codegen_unit( &self, tcx: TyCtxt<'_>, - cgu_name: Symbol, + cgu_name: InternedString, tx: &std::sync::mpsc::Sender>, ) { base::compile_codegen_unit(tcx, cgu_name, tx); @@ -256,19 +258,28 @@ impl CodegenBackend for LlvmCodegenBackend { llvm_util::print_version(); } + fn diagnostics(&self) -> &[(&'static str, &'static str)] { + &error_codes::DIAGNOSTICS + } + fn target_features(&self, sess: &Session) -> Vec { target_features(sess) } - fn metadata_loader(&self) -> Box { + fn metadata_loader(&self) -> Box { box metadata::LlvmMetadataLoader } fn provide(&self, providers: &mut ty::query::Providers<'_>) { + rustc_codegen_utils::symbol_names::provide(providers); + rustc_codegen_ssa::back::symbol_export::provide(providers); + rustc_codegen_ssa::base::provide_both(providers); attributes::provide(providers); } fn provide_extern(&self, providers: &mut ty::query::Providers<'_>) { + rustc_codegen_ssa::back::symbol_export::provide_extern(providers); + rustc_codegen_ssa::base::provide_both(providers); attributes::provide_extern(providers); } @@ -312,9 +323,8 @@ impl CodegenBackend for LlvmCodegenBackend { // Run the linker on any artifacts that resulted from the LLVM run. // This should produce either a finished executable or library. + sess.profiler(|p| p.start_activity("link_crate")); time(sess, "linking", || { - let _prof_timer = sess.prof.generic_activity("link_crate"); - use rustc_codegen_ssa::back::link::link_binary; use crate::back::archive::LlvmArchiveBuilder; @@ -327,6 +337,7 @@ impl CodegenBackend for LlvmCodegenBackend { target_cpu, ); }); + sess.profiler(|p| p.end_activity("link_crate")); // Now that we won't touch anything in the incremental compilation directory // any more, we can finalize it (which involves renaming it) diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index c69942ef3f2d5..b07214fdc03f3 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -50,7 +50,7 @@ pub enum CallConv { } /// LLVMRustLinkage -#[derive(PartialEq)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[repr(C)] pub enum Linkage { ExternalLinkage = 0, @@ -67,6 +67,7 @@ pub enum Linkage { } // LLVMRustVisibility +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[repr(C)] pub enum Visibility { Default = 0, @@ -509,7 +510,6 @@ extern { pub type Module; } extern { pub type Context; } extern { pub type Type; } extern { pub type Value; } -extern { pub type ConstantInt; } extern { pub type Metadata; } extern { pub type BasicBlock; } #[repr(C)] @@ -719,8 +719,8 @@ extern "C" { pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value; pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value; pub fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value; - pub fn LLVMConstIntGetZExtValue(ConstantVal: &ConstantInt) -> c_ulonglong; - pub fn LLVMRustConstInt128Get(ConstantVal: &ConstantInt, SExt: bool, + pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong; + pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: bool, high: &mut u64, low: &mut u64) -> bool; @@ -1666,7 +1666,7 @@ extern "C" { #[allow(improper_ctypes)] pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); - pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>; + pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&Value>; pub fn LLVMRustPassKind(Pass: &Pass) -> PassKind; pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>; diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 2dce9b04c9e9e..541d3d98b79bd 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -257,7 +257,8 @@ pub fn target_feature_whitelist(sess: &Session) "hexagon" => HEXAGON_WHITELIST, "mips" | "mips64" => MIPS_WHITELIST, "powerpc" | "powerpc64" => POWERPC_WHITELIST, - "wasm32" => WASM_WHITELIST, + // wasm32 on emscripten does not support these target features + "wasm32" if !sess.target.target.options.is_like_emscripten => WASM_WHITELIST, _ => &[], } } diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index d921bbc96adee..81a99bc5019b3 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -65,7 +65,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, if let (&ty::Generator(_, substs, _), &layout::Variants::Single { index }) = (&layout.ty.kind, &layout.variants) { - write!(&mut name, "::{}", substs.as_generator().variant_name(index)).unwrap(); + write!(&mut name, "::{}", substs.variant_name(index)).unwrap(); } Some(name) } diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index 6992f93d99949..2e3666e609657 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -21,7 +21,6 @@ tempfile = "3.1" rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } -syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } rustc = { path = "../librustc" } rustc_apfloat = { path = "../librustc_apfloat" } @@ -30,5 +29,4 @@ rustc_data_structures = { path = "../librustc_data_structures"} rustc_errors = { path = "../librustc_errors" } rustc_fs_util = { path = "../librustc_fs_util" } rustc_incremental = { path = "../librustc_incremental" } -rustc_index = { path = "../librustc_index" } rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_codegen_ssa/README.md b/src/librustc_codegen_ssa/README.md index a09a0c22c1ba5..c8bb2e7ee9965 100644 --- a/src/librustc_codegen_ssa/README.md +++ b/src/librustc_codegen_ssa/README.md @@ -84,7 +84,7 @@ pub trait BuilderMethods<'a, 'tcx>: { fn new_block<'b>( cx: &'a Self::CodegenCx, - llfn: Self::Function, + llfn: Self::Value, name: &'b str ) -> Self; /* ... */ diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 1c5d3b1a890ee..3b7ae5e33d5e7 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -323,7 +323,6 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, NativeLibraryKind::NativeStatic => {} NativeLibraryKind::NativeStaticNobundle | NativeLibraryKind::NativeFramework | - NativeLibraryKind::NativeRawDylib | NativeLibraryKind::NativeUnknown => continue, } if let Some(name) = lib.name { @@ -884,8 +883,7 @@ pub fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary Some(format!("-framework {}", name)) }, // These are included, no need to print them - NativeLibraryKind::NativeStatic | - NativeLibraryKind::NativeRawDylib => None, + NativeLibraryKind::NativeStatic => None, } }) .collect(); @@ -1295,11 +1293,7 @@ pub fn add_local_native_libraries(cmd: &mut dyn Linker, 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), - NativeLibraryKind::NativeRawDylib => { - // FIXME(#58713): Proper handling for raw dylibs. - bug!("raw_dylib feature not yet implemented"); - }, + NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(name, &search_path) } } } @@ -1391,9 +1385,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => { add_static_crate::(cmd, sess, codegen_results, tmpdir, crate_type, cnum); } - _ if codegen_results.crate_info.sanitizer_runtime == Some(cnum) && - crate_type == config::CrateType::Executable => { - // Link the sanitizer runtimes only if we are actually producing an executable + _ if codegen_results.crate_info.sanitizer_runtime == Some(cnum) => { link_sanitizer_runtime::(cmd, sess, codegen_results, tmpdir, cnum); } // compiler-builtins are always placed last to ensure that they're @@ -1535,7 +1527,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let name = cratepath.file_name().unwrap().to_str().unwrap(); let name = &name[3..name.len() - 5]; // chop off lib/.rlib - time_ext(sess.time_extended(), &format!("altering {}.rlib", name), || { + time_ext(sess.time_extended(), Some(sess), &format!("altering {}.rlib", name), || { let mut archive = ::new(sess, &dst, Some(cratepath)); archive.update_symbols(); @@ -1686,11 +1678,7 @@ pub fn add_upstream_native_libraries( // ignore statically included native libraries here as we've // already included them when we included the rust library // previously - NativeLibraryKind::NativeStatic => {}, - NativeLibraryKind::NativeRawDylib => { - // FIXME(#58713): Proper handling for raw dylibs. - bug!("raw_dylib feature not yet implemented"); - }, + NativeLibraryKind::NativeStatic => {} } } } diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index d866a10f06935..d634b73430a58 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -13,8 +13,8 @@ use rustc::ty::{TyCtxt, SymbolName}; use rustc::ty::query::Providers; use rustc::ty::subst::SubstsRef; use rustc::util::nodemap::{FxHashMap, DefIdMap}; -use rustc_index::vec::IndexVec; -use syntax_expand::allocator::ALLOCATOR_METHODS; +use rustc_data_structures::indexed_vec::IndexVec; +use syntax::ext::allocator::ALLOCATOR_METHODS; pub type ExportedSymbols = FxHashMap< CrateNum, diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 762b50f1659cc..3c5fbfd0f866f 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -19,19 +19,19 @@ use rustc::util::nodemap::FxHashMap; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::ty::TyCtxt; use rustc::util::common::{time_depth, set_time_depth, print_time_passes_entry}; -use rustc::util::profiling::SelfProfilerRef; +use rustc::util::profiling::SelfProfiler; use rustc_fs_util::link_or_copy; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::Lrc; -use rustc_errors::{Handler, Level, FatalError, DiagnosticId, SourceMapperDyn}; +use rustc_errors::{Handler, Level, FatalError, DiagnosticId}; use rustc_errors::emitter::{Emitter}; use rustc_target::spec::MergeFunctions; use syntax::attr; -use syntax_expand::hygiene::ExpnId; +use syntax::ext::hygiene::ExpnId; use syntax_pos::symbol::{Symbol, sym}; use jobserver::{Client, Acquired}; use std::any::Any; +use std::borrow::Cow; use std::fs; use std::io; use std::mem; @@ -143,12 +143,15 @@ impl ModuleConfig { // Copy what clang does by turning on loop vectorization at O2 and // slp vectorization at O3. Otherwise configure other optimization aspects // of this pass manager builder. + // Turn off vectorization for emscripten, as it's not very well supported. self.vectorize_loop = !sess.opts.cg.no_vectorize_loops && (sess.opts.optimize == config::OptLevel::Default || - sess.opts.optimize == config::OptLevel::Aggressive); + sess.opts.optimize == config::OptLevel::Aggressive) && + !sess.target.target.options.is_like_emscripten; self.vectorize_slp = !sess.opts.cg.no_vectorize_slp && - sess.opts.optimize == config::OptLevel::Aggressive; + sess.opts.optimize == config::OptLevel::Aggressive && + !sess.target.target.options.is_like_emscripten; // Some targets (namely, NVPTX) interact badly with the MergeFunctions // pass. This is because MergeFunctions can generate new function calls @@ -193,13 +196,42 @@ impl Clone for TargetMachineFactory { } } +pub struct ProfileGenericActivityTimer { + profiler: Option>, + label: Cow<'static, str>, +} + +impl ProfileGenericActivityTimer { + pub fn start( + profiler: Option>, + label: Cow<'static, str>, + ) -> ProfileGenericActivityTimer { + if let Some(profiler) = &profiler { + profiler.start_activity(label.clone()); + } + + ProfileGenericActivityTimer { + profiler, + label, + } + } +} + +impl Drop for ProfileGenericActivityTimer { + fn drop(&mut self) { + if let Some(profiler) = &self.profiler { + profiler.end_activity(self.label.clone()); + } + } +} + /// Additional resources used by optimize_and_codegen (not module specific) #[derive(Clone)] pub struct CodegenContext { // Resources needed when running LTO pub backend: B, pub time_passes: bool, - pub prof: SelfProfilerRef, + pub profiler: Option>, pub lto: Lto, pub no_landing_pads: bool, pub save_temps: bool, @@ -251,6 +283,31 @@ impl CodegenContext { ModuleKind::Allocator => &self.allocator_module_config, } } + + #[inline(never)] + #[cold] + fn profiler_active ()>(&self, f: F) { + match &self.profiler { + None => bug!("profiler_active() called but there was no profiler active"), + Some(profiler) => { + f(&*profiler); + } + } + } + + #[inline(always)] + pub fn profile ()>(&self, f: F) { + if unlikely!(self.profiler.is_some()) { + self.profiler_active(f) + } + } + + pub fn profile_activity( + &self, + label: impl Into>, + ) -> ProfileGenericActivityTimer { + ProfileGenericActivityTimer::start(self.profiler.clone(), label.into()) + } } fn generate_lto_work( @@ -259,7 +316,7 @@ fn generate_lto_work( needs_thin_lto: Vec<(String, B::ThinBuffer)>, import_only_modules: Vec<(SerializedModule, WorkProduct)> ) -> Vec<(WorkItem, u64)> { - let _prof_timer = cgcx.prof.generic_activity("codegen_generate_lto_work"); + cgcx.profile(|p| p.start_activity("codegen_run_lto")); let (lto_modules, copy_jobs) = if !needs_fat_lto.is_empty() { assert!(needs_thin_lto.is_empty()); @@ -286,6 +343,8 @@ fn generate_lto_work( }), 0) })).collect(); + cgcx.profile(|p| p.end_activity("codegen_run_lto")); + result } @@ -321,7 +380,6 @@ pub fn start_async_codegen( ) -> OngoingCodegen { let (coordinator_send, coordinator_receive) = channel(); let sess = tcx.sess; - let crate_name = tcx.crate_name(LOCAL_CRATE); let crate_hash = tcx.crate_hash(LOCAL_CRATE); let no_builtins = attr::contains_name(&tcx.hir().krate().attrs, sym::no_builtins); @@ -674,11 +732,11 @@ impl WorkItem { } } - fn profiling_event_id(&self) -> &'static str { + pub fn name(&self) -> String { match *self { - WorkItem::Optimize(_) => "codegen_module_optimize", - WorkItem::CopyPostLtoArtifacts(_) => "codegen_copy_artifacts_from_incr_cache", - WorkItem::LTO(_) => "codegen_module_perform_lto", + WorkItem::Optimize(ref m) => format!("optimize: {}", m.name), + WorkItem::CopyPostLtoArtifacts(ref m) => format!("copy post LTO artifacts: {}", m.name), + WorkItem::LTO(ref m) => format!("lto: {}", m.name()), } } } @@ -1030,7 +1088,7 @@ fn start_executing_work( save_temps: sess.opts.cg.save_temps, opts: Arc::new(sess.opts.clone()), time_passes: sess.time_extended(), - prof: sess.prof.clone(), + profiler: sess.self_profiling.clone(), exported_symbols, plugin_passes: sess.plugin_llvm_passes.borrow().clone(), remark: sess.opts.cg.remark.clone(), @@ -1587,8 +1645,12 @@ fn spawn_work( // as a diagnostic was already sent off to the main thread - just // surface that there was an error in this worker. bomb.result = { - let _prof_timer = cgcx.prof.generic_activity(work.profiling_event_id()); - execute_work_item(&cgcx, work).ok() + let label = work.name(); + cgcx.profile(|p| p.start_activity(label.clone())); + let result = execute_work_item(&cgcx, work).ok(); + cgcx.profile(|p| p.end_activity(label)); + + result }; }); } @@ -1664,13 +1726,13 @@ impl SharedEmitter { } impl Emitter for SharedEmitter { - fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { + fn emit_diagnostic(&mut self, db: &rustc_errors::Diagnostic) { drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - msg: diag.message(), - code: diag.code.clone(), - lvl: diag.level, + msg: db.message(), + code: db.code.clone(), + lvl: db.level, }))); - for child in &diag.children { + for child in &db.children { drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { msg: child.message(), code: None, @@ -1679,9 +1741,6 @@ impl Emitter for SharedEmitter { } drop(self.sender.send(SharedEmitterMessage::AbortIfErrors)); } - fn source_map(&self) -> Option<&Lrc> { - None - } } impl SharedEmitterMain { diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index bf687f846357e..90ed629bbc61e 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -29,13 +29,14 @@ use rustc::util::common::{time, print_time_passes_entry, set_time_depth, time_de use rustc::session::config::{self, EntryFnType, Lto}; use rustc::session::Session; use rustc::util::nodemap::FxHashMap; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use rustc_codegen_utils::{symbol_names_test, check_for_rustc_errors_attr}; use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; use crate::mir::place::PlaceRef; use crate::back::write::{OngoingCodegen, start_async_codegen, submit_pre_lto_module_to_llvm, submit_post_lto_module_to_llvm}; use crate::{MemFlags, CrateInfo}; +use crate::callee; use crate::common::{RealPredicate, TypeKind, IntPredicate}; use crate::meth; use crate::mir; @@ -168,6 +169,12 @@ pub fn unsize_thin_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(bx.cx().layout_of(b))); (bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None)) } + (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { + let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty()); + assert!(bx.cx().type_is_sized(a)); + let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(bx.cx().layout_of(b))); + (bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None)) + } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); @@ -190,8 +197,6 @@ pub fn unsize_thin_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } let (lldata, llextra) = result.unwrap(); // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. - // FIXME(eddyb) move these out of this `match` arm, so they're always - // applied, uniformly, no matter the source/destination types. (bx.bitcast(lldata, bx.cx().scalar_pair_element_backend_type(dst_layout, 0, true)), bx.bitcast(llextra, bx.cx().scalar_pair_element_backend_type(dst_layout, 1, true))) } @@ -208,27 +213,31 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) { let src_ty = src.layout.ty; let dst_ty = dst.layout.ty; + let mut coerce_ptr = || { + let (base, info) = match bx.load_operand(src).val { + OperandValue::Pair(base, info) => { + // fat-ptr to fat-ptr unsize preserves the vtable + // i.e., &'a fmt::Debug+Send => &'a fmt::Debug + // So we need to pointercast the base to ensure + // the types match up. + let thin_ptr = dst.layout.field(bx.cx(), FAT_PTR_ADDR); + (bx.pointercast(base, bx.cx().backend_type(thin_ptr)), info) + } + OperandValue::Immediate(base) => { + unsize_thin_ptr(bx, base, src_ty, dst_ty) + } + OperandValue::Ref(..) => bug!() + }; + OperandValue::Pair(base, info).store(bx, dst); + }; match (&src_ty.kind, &dst_ty.kind) { (&ty::Ref(..), &ty::Ref(..)) | (&ty::Ref(..), &ty::RawPtr(..)) | (&ty::RawPtr(..), &ty::RawPtr(..)) => { - let (base, info) = match bx.load_operand(src).val { - OperandValue::Pair(base, info) => { - // fat-ptr to fat-ptr unsize preserves the vtable - // i.e., &'a fmt::Debug+Send => &'a fmt::Debug - // So we need to pointercast the base to ensure - // the types match up. - // FIXME(eddyb) use `scalar_pair_element_backend_type` here, - // like `unsize_thin_ptr` does. - let thin_ptr = dst.layout.field(bx.cx(), FAT_PTR_ADDR); - (bx.pointercast(base, bx.cx().backend_type(thin_ptr)), info) - } - OperandValue::Immediate(base) => { - unsize_thin_ptr(bx, base, src_ty, dst_ty) - } - OperandValue::Ref(..) => bug!() - }; - OperandValue::Pair(base, info).store(bx, dst); + coerce_ptr() + } + (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { + coerce_ptr() } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { @@ -368,7 +377,8 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( let sig = instance.fn_sig(cx.tcx()); let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - let lldecl = cx.get_fn(instance); + let lldecl = cx.instances().borrow().get(&instance).cloned().unwrap_or_else(|| + bug!("Instance `{:?}` not already declared", instance)); let mir = cx.tcx().instance_mir(instance.def); mir::codegen_mir::(cx, lldecl, &mir, instance, sig); @@ -390,7 +400,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' return; } - let main_llfn = cx.get_fn_addr(instance); + let main_llfn = cx.get_fn(instance); let et = cx.tcx().entry_fn(LOCAL_CRATE).map(|e| e.1); match et { @@ -406,13 +416,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' rust_main_def_id: DefId, use_start_lang_item: bool, ) { - // The entry function is either `int main(void)` or `int main(int argc, char **argv)`, - // depending on whether the target needs `argc` and `argv` to be passed in. - let llfty = if cx.sess().target.target.options.main_needs_argc_argv { - cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int()) - } else { - cx.type_func(&[], cx.type_int()) - }; + let llfty = + cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int()); let main_ret_ty = cx.tcx().fn_sig(rust_main_def_id).output(); // Given that `main()` has no arguments, @@ -442,17 +447,18 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' bx.insert_reference_to_gdb_debug_scripts_section_global(); - let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx); + // Params from native main() used as args for rust start function + let param_argc = bx.get_param(0); + let param_argv = bx.get_param(1); + let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); + let arg_argv = param_argv; let (start_fn, args) = if use_start_lang_item { let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None); - let start_fn = cx.get_fn_addr( - ty::Instance::resolve( - cx.tcx(), - ty::ParamEnv::reveal_all(), - start_def_id, - cx.tcx().intern_substs(&[main_ret_ty.into()]), - ).unwrap() + let start_fn = callee::resolve_and_get_fn( + cx, + start_def_id, + cx.tcx().intern_substs(&[main_ret_ty.into()]), ); (start_fn, vec![bx.pointercast(rust_main, cx.type_ptr_to(cx.type_i8p())), arg_argc, arg_argv]) @@ -467,27 +473,6 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' } } -/// Obtain the `argc` and `argv` values to pass to the rust start function. -fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - cx: &'a Bx::CodegenCx, - bx: &mut Bx -) -> (Bx::Value, Bx::Value) -{ - if cx.sess().target.target.options.main_needs_argc_argv { - // Params from native `main()` used as args for rust start function - let param_argc = bx.get_param(0); - let param_argv = bx.get_param(1); - let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); - let arg_argv = param_argv; - (arg_argc, arg_argv) - } else { - // The Rust start function doesn't need `argc` and `argv`, so just pass zeros. - let arg_argc = bx.const_int(cx.type_int(), 0); - let arg_argv = bx.const_null(cx.type_ptr_to(cx.type_i8p())); - (arg_argc, arg_argv) - } -} - pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX; pub fn codegen_crate( @@ -526,7 +511,7 @@ pub fn codegen_crate( // unnecessarily. if tcx.dep_graph.is_fully_enabled() { for cgu in &codegen_units { - tcx.codegen_unit(cgu.name()); + tcx.codegen_unit(cgu.name().clone()); } } @@ -574,7 +559,7 @@ pub fn codegen_crate( if need_metadata_module { // Codegen the encoded metadata. - let _prof_timer = tcx.prof.generic_activity("codegen_crate_metadata"); + tcx.sess.profiler(|p| p.start_activity("codegen crate metadata")); let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], @@ -585,6 +570,7 @@ pub fn codegen_crate( backend.write_compressed_metadata(tcx, &ongoing_codegen.metadata, &mut metadata_llvm_module); }); + tcx.sess.profiler(|p| p.end_activity("codegen crate metadata")); let metadata_module = ModuleCodegen { name: metadata_cgu_name, @@ -613,9 +599,11 @@ pub fn codegen_crate( match cgu_reuse { CguReuse::No => { + tcx.sess.profiler(|p| p.start_activity(format!("codegen {}", cgu.name()))); let start_time = Instant::now(); - backend.compile_codegen_unit(tcx, cgu.name(), &ongoing_codegen.coordinator_send); + backend.compile_codegen_unit(tcx, *cgu.name(), &ongoing_codegen.coordinator_send); total_codegen_time += start_time.elapsed(); + tcx.sess.profiler(|p| p.end_activity(format!("codegen {}", cgu.name()))); false } CguReuse::PreLto => { diff --git a/src/librustc_codegen_ssa/callee.rs b/src/librustc_codegen_ssa/callee.rs new file mode 100644 index 0000000000000..4744dd6302fb3 --- /dev/null +++ b/src/librustc_codegen_ssa/callee.rs @@ -0,0 +1,36 @@ +use crate::traits::*; +use rustc::ty; +use rustc::ty::subst::SubstsRef; +use rustc::hir::def_id::DefId; + +pub fn resolve_and_get_fn<'tcx, Cx: CodegenMethods<'tcx>>( + cx: &Cx, + def_id: DefId, + substs: SubstsRef<'tcx>, +) -> Cx::Value { + cx.get_fn( + ty::Instance::resolve( + cx.tcx(), + ty::ParamEnv::reveal_all(), + def_id, + substs + ).unwrap() + ) +} + +pub fn resolve_and_get_fn_for_vtable<'tcx, + Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx> +>( + cx: &Cx, + def_id: DefId, + substs: SubstsRef<'tcx>, +) -> Cx::Value { + cx.get_fn( + ty::Instance::resolve_for_vtable( + cx.tcx(), + ty::ParamEnv::reveal_all(), + def_id, + substs + ).unwrap() + ) +} diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs index ac39ca9847667..6376512ca4025 100644 --- a/src/librustc_codegen_ssa/common.rs +++ b/src/librustc_codegen_ssa/common.rs @@ -1,7 +1,6 @@ #![allow(non_camel_case_types, non_snake_case)] use rustc::ty::{Ty, TyCtxt}; -use rustc::session::Session; use syntax_pos::Span; use rustc::hir::def_id::DefId; @@ -110,11 +109,14 @@ pub enum TypeKind { // for now we content ourselves with providing a no-op HashStable // implementation for CGUs. mod temp_stable_hash_impls { - use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; + use rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher, + HashStable}; use crate::ModuleCodegen; impl HashStable for ModuleCodegen { - fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) { + fn hash_stable(&self, + _: &mut HCX, + _: &mut StableHasher) { // do nothing } } @@ -201,7 +203,3 @@ pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind), } } - -pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) { - span_err!(a, b, E0511, "{}", c); -} diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs index 166a74fe48795..d875c60959cba 100644 --- a/src/librustc_codegen_ssa/debuginfo/type_names.rs +++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs @@ -221,7 +221,7 @@ pub fn push_debuginfo_type_name<'tcx>( output.push_str(&tcx.crate_name(def_id.krate).as_str()); for path_element in tcx.def_path(def_id).data { output.push_str("::"); - output.push_str(&path_element.data.as_symbol().as_str()); + output.push_str(&path_element.data.as_interned_str().as_str()); } } else { output.push_str(&tcx.item_name(def_id).as_str()); diff --git a/src/librustc_codegen_ssa/error_codes.rs b/src/librustc_codegen_ssa/error_codes.rs index 02e26d8f6ecf0..8ff41c275a8f4 100644 --- a/src/librustc_codegen_ssa/error_codes.rs +++ b/src/librustc_codegen_ssa/error_codes.rs @@ -1,40 +1,5 @@ syntax::register_diagnostics! { -E0511: r##" -Invalid monomorphization of an intrinsic function was used. Erroneous code -example: - -```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail) -#![feature(platform_intrinsics)] - -extern "platform-intrinsic" { - fn simd_add(a: T, b: T) -> T; -} - -fn main() { - unsafe { simd_add(0, 1); } - // error: invalid monomorphization of `simd_add` intrinsic -} -``` - -The generic type has to be a SIMD type. Example: - -``` -#![feature(repr_simd)] -#![feature(platform_intrinsics)] - -#[repr(simd)] -#[derive(Copy, Clone)] -struct i32x2(i32, i32); - -extern "platform-intrinsic" { - fn simd_add(a: T, b: T) -> T; -} - -unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok! -``` -"##, - 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 0221a04b04518..161d3ce61f0a6 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -10,6 +10,7 @@ #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(trusted_len)] +#![feature(mem_take)] #![feature(associated_type_bounds)] #![recursion_limit="256"] @@ -20,6 +21,7 @@ #[macro_use] extern crate log; #[macro_use] extern crate rustc; +#[macro_use] extern crate rustc_data_structures; #[macro_use] extern crate syntax; use std::path::PathBuf; @@ -27,7 +29,6 @@ use rustc::dep_graph::WorkProduct; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::middle::lang_items::LangItem; use rustc::hir::def_id::CrateNum; -use rustc::ty::query::Providers; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::svh::Svh; @@ -42,6 +43,7 @@ pub mod traits; pub mod mir; pub mod debuginfo; pub mod base; +pub mod callee; pub mod glue; pub mod meth; pub mod mono_item; @@ -156,13 +158,3 @@ pub struct CodegenResults { pub linker_info: back::linker::LinkerInfo, pub crate_info: CrateInfo, } - -pub fn provide(providers: &mut Providers<'_>) { - crate::back::symbol_export::provide(providers); - crate::base::provide_both(providers); -} - -pub fn provide_extern(providers: &mut Providers<'_>) { - crate::back::symbol_export::provide_extern(providers); - crate::base::provide_both(providers); -} diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs index 266d2e5b18d22..7fe9f5f25130a 100644 --- a/src/librustc_codegen_ssa/meth.rs +++ b/src/librustc_codegen_ssa/meth.rs @@ -1,5 +1,6 @@ use rustc_target::abi::call::FnType; +use crate::callee; use crate::traits::*; use rustc::ty::{self, Ty, Instance}; @@ -91,14 +92,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( let methods = methods.cloned().map(|opt_mth| { opt_mth.map_or(nullptr, |(def_id, substs)| { - cx.get_fn_addr( - ty::Instance::resolve_for_vtable( - cx.tcx(), - ty::ParamEnv::reveal_all(), - def_id, - substs, - ).unwrap() - ) + callee::resolve_and_get_fn_for_vtable(cx, def_id, substs) }) }); @@ -108,7 +102,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( // `get_vtable` in rust_mir/interpret/traits.rs // ///////////////////////////////////////////////////////////////////////////////////////////// let components: Vec<_> = [ - cx.get_fn_addr(Instance::resolve_drop_in_place(cx.tcx(), ty)), + cx.get_fn(Instance::resolve_drop_in_place(cx.tcx(), ty)), cx.const_usize(layout.size.bytes()), cx.const_usize(layout.align.abi.bytes()) ].iter().cloned().chain(methods).collect(); diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 604deffcf949b..05896523863c2 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -1,9 +1,9 @@ //! An analysis to determine which locals require allocas and //! which do not. -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::graph::dominators::Dominators; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::{self, Location, TerminatorKind}; use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext}; use rustc::mir::traversal; @@ -191,7 +191,10 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> location: Location) { debug!("visit_assign(place={:?}, rvalue={:?})", place, rvalue); - if let Some(index) = place.as_local() { + if let mir::Place { + base: mir::PlaceBase::Local(index), + projection: box [], + } = *place { self.assign(index, location); let decl_span = self.fx.mir.local_decls[index].source_info.span; if !self.fx.rvalue_creates_operand(rvalue, decl_span) { diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 28441cae26e3f..3069199a21256 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -1,10 +1,9 @@ -use rustc_index::vec::Idx; use rustc::middle::lang_items; use rustc::ty::{self, Ty, TypeFoldable, Instance}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnTypeExt}; -use rustc::mir::{self, PlaceBase, Static, StaticKind}; +use rustc::mir::{self, Place, PlaceBase, Static, StaticKind}; use rustc::mir::interpret::PanicInfo; -use rustc_target::abi::call::{ArgType, FnType, PassMode}; +use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode}; use rustc_target::spec::abi::Abi; use crate::base; use crate::MemFlags; @@ -149,26 +148,6 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } } } - - // Generate sideeffect intrinsic if jumping to any of the targets can form - // a loop. - fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>( - &self, - mir: &'b mir::Body<'tcx>, - bx: &mut Bx, - targets: &[mir::BasicBlock], - ) { - if bx.tcx().sess.opts.debugging_opts.insert_sideeffect { - if targets.iter().any(|target| { - *target <= *self.bb - && target - .start_location() - .is_predecessor_of(self.bb.start_location(), mir) - }) { - bx.sideeffect(); - } - } - } } /// Codegen implementations for some terminator variants. @@ -217,7 +196,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let lltrue = helper.llblock(self, targets[0]); let llfalse = helper.llblock(self, targets[1]); if switch_ty == bx.tcx().types.bool { - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); // Don't generate trivial icmps when switching on bool if let [0] = values[..] { bx.cond_br(discr.immediate(), llfalse, lltrue); @@ -231,11 +209,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ); let llval = bx.const_uint_big(switch_llty, values[0]); let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval); - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); bx.cond_br(cmp, lltrue, llfalse); } } else { - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); let (otherwise, targets) = targets.split_last().unwrap(); bx.switch( discr.immediate(), @@ -248,15 +224,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } fn codegen_return_terminator(&mut self, mut bx: Bx) { - // Call `va_end` if this is the definition of a C-variadic function. if self.fn_ty.c_variadic { - // The `VaList` "spoofed" argument is just after all the real arguments. - let va_list_arg_idx = self.fn_ty.args.len(); - match self.locals[mir::Local::new(1 + va_list_arg_idx)] { - LocalRef::Place(va_list) => { + match self.va_list_ref { + Some(va_list) => { bx.va_end(va_list.llval); } - _ => bug!("C-variadic function must have a `VaList` place"), + None => { + bug!("C-variadic function must have a `va_list_ref`"); + } } } if self.fn_ty.ret.layout.abi.is_uninhabited() { @@ -267,11 +242,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } let llval = match self.fn_ty.ret.mode { - PassMode::Ignore | PassMode::Indirect(..) => { + PassMode::Ignore(IgnoreMode::Zst) | PassMode::Indirect(..) => { bx.ret_void(); return; } + PassMode::Ignore(IgnoreMode::CVarArgs) => { + bug!("C-variadic arguments should never be the return type"); + } + PassMode::Direct(_) | PassMode::Pair(..) => { let op = self.codegen_consume(&mut bx, &mir::Place::return_place().as_ref()); @@ -331,7 +310,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def { // we don't actually need to drop anything. - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); return } @@ -358,11 +336,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_ty), fn_ty) } _ => { - (bx.get_fn_addr(drop_fn), + (bx.get_fn(drop_fn), FnType::of_instance(&bx, drop_fn)) } }; - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.do_call(self, &mut bx, fn_ty, drop_fn, args, Some((ReturnDest::Nothing, target)), unwind); @@ -398,7 +375,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Don't codegen the panic block if success if known. if const_cond == Some(expected) { - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); return; } @@ -409,7 +385,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Create the failure block and the conditional branch to it. let lltarget = helper.llblock(self, target); let panic_block = self.new_block("panic"); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); if expected { bx.cond_br(cond, lltarget, panic_block.llbb()); } else { @@ -460,7 +435,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item); let instance = ty::Instance::mono(bx.tcx(), def_id); let fn_ty = FnType::of_instance(&bx, instance); - let llfn = bx.get_fn_addr(instance); + let llfn = bx.get_fn(instance); // Codegen the actual panic invoke/call. helper.do_call(self, &mut bx, fn_ty, llfn, &args, None, cleanup); @@ -513,7 +488,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let Some(destination_ref) = destination.as_ref() { let &(ref dest, target) = destination_ref; self.codegen_transmute(&mut bx, &args[0], dest); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); } else { // If we are trying to transmute to an uninhabited type, @@ -528,7 +502,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } - let extra_args = &args[sig.inputs().len()..]; + // The "spoofed" `VaListImpl` added to a C-variadic functions signature + // should not be included in the `extra_args` calculation. + let extra_args_start_idx = sig.inputs().len() - if sig.c_variadic { 1 } else { 0 }; + let extra_args = &args[extra_args_start_idx..]; let extra_args = extra_args.iter().map(|op_arg| { let op_ty = op_arg.ty(self.mir, bx.tcx()); self.monomorphize(&op_ty) @@ -541,7 +518,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Some(ty::InstanceDef::DropGlue(_, None)) => { // Empty drop glue; a no-op. let &(_, target) = destination.as_ref().unwrap(); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); return; } @@ -576,11 +552,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem); let instance = ty::Instance::mono(bx.tcx(), def_id); let fn_ty = FnType::of_instance(&bx, instance); - let llfn = bx.get_fn_addr(instance); + let llfn = bx.get_fn(instance); - if let Some((_, target)) = destination.as_ref() { - helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); - } // Codegen the actual panic invoke/call. helper.do_call( self, @@ -593,9 +566,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ); } else { // a NOP - let target = destination.as_ref().unwrap().1; - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); + helper.funclet_br(self, &mut bx, destination.as_ref().unwrap().1) } return; } @@ -630,43 +601,53 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // checked by const-qualification, which also // promotes any complex rvalues to constants. if i == 2 && intrinsic.unwrap().starts_with("simd_shuffle") { - match arg { + match *arg { // The shuffle array argument is usually not an explicit constant, // but specified directly in the code. This means it gets promoted // and we can then extract the value by evaluating the promoted. - mir::Operand::Copy(place) | mir::Operand::Move(place) => { - if let mir::PlaceRef { - base: - &PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted, _), - ty, - def_id: _, - }), - projection: &[], - } = place.as_ref() - { - let param_env = ty::ParamEnv::reveal_all(); - let cid = mir::interpret::GlobalId { - instance: self.instance, - promoted: Some(promoted), - }; - let c = bx.tcx().const_eval(param_env.and(cid)); - let (llval, ty) = self.simd_shuffle_indices( - &bx, - terminator.source_info.span, + mir::Operand::Copy( + Place { + base: PlaceBase::Static(box Static { + kind: StaticKind::Promoted(promoted, _), ty, - c, - ); - return OperandRef { - val: Immediate(llval), - layout: bx.layout_of(ty), - }; - } else { - span_bug!(span, "shuffle indices must be constant"); + def_id: _, + }), + projection: box [], } - } + ) | + mir::Operand::Move( + Place { + base: PlaceBase::Static(box Static { + kind: StaticKind::Promoted(promoted, _), + ty, + def_id: _, + }), + projection: box [], + } + ) => { + let param_env = ty::ParamEnv::reveal_all(); + let cid = mir::interpret::GlobalId { + instance: self.instance, + promoted: Some(promoted), + }; + let c = bx.tcx().const_eval(param_env.and(cid)); + let (llval, ty) = self.simd_shuffle_indices( + &bx, + terminator.source_info.span, + ty, + c, + ); + return OperandRef { + val: Immediate(llval), + layout: bx.layout_of(ty), + }; - mir::Operand::Constant(constant) => { + } + mir::Operand::Copy(_) | + mir::Operand::Move(_) => { + span_bug!(span, "shuffle indices must be constant"); + } + mir::Operand::Constant(ref constant) => { let c = self.eval_mir_constant(constant); let (llval, ty) = self.simd_shuffle_indices( &bx, @@ -694,7 +675,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } if let Some((_, target)) = *destination { - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); } else { bx.unreachable(); @@ -711,7 +691,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (&args[..], None) }; + // Useful determining if the current argument is the "spoofed" `VaListImpl` + let last_arg_idx = if sig.inputs().is_empty() { + None + } else { + Some(sig.inputs().len() - 1) + }; 'make_args: for (i, arg) in first_args.iter().enumerate() { + // If this is a C-variadic function the function signature contains + // an "spoofed" `VaListImpl`. This argument is ignored, but we need to + // populate it with a dummy operand so that the users real arguments + // are not overwritten. + let i = if sig.c_variadic && last_arg_idx.map(|x| i >= x).unwrap_or(false) { + if i + 1 < fn_ty.args.len() { + i + 1 + } else { + break 'make_args + } + } else { + i + }; let mut op = self.codegen_operand(&mut bx, arg); if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) { @@ -783,13 +782,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_ptr = match (llfn, instance) { (Some(llfn), _) => llfn, - (None, Some(instance)) => bx.get_fn_addr(instance), + (None, Some(instance)) => bx.get_fn(instance), _ => span_bug!(span, "no llfn for call"), }; - if let Some((_, target)) = destination.as_ref() { - helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); - } helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs, destination.as_ref().map(|&(_, target)| (ret_dest, target)), cleanup); @@ -839,7 +835,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::TerminatorKind::Goto { target } => { - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); } @@ -1107,7 +1102,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if fn_ret.is_ignore() { return ReturnDest::Nothing; } - let dest = if let Some(index) = dest.as_local() { + let dest = if let mir::Place { + base: mir::PlaceBase::Local(index), + projection: box [], + } = *dest { match self.locals[index] { LocalRef::Place(dest) => dest, LocalRef::UnsizedPlace(_) => bug!("return type must be sized"), @@ -1165,7 +1163,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { src: &mir::Operand<'tcx>, dst: &mir::Place<'tcx> ) { - if let Some(index) = dst.as_local() { + if let mir::Place { + base: mir::PlaceBase::Local(index), + projection: box [], + } = *dst { match self.locals[index] { LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place), LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"), diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index d06359ab0ce89..9cfe410fcc5e0 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -1,6 +1,6 @@ use rustc::mir::interpret::ErrorHandled; use rustc::mir; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, HasTyCtxt}; use syntax::source_map::Span; diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 1a2e796a5b7be..c341c0685c6a7 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -2,7 +2,7 @@ use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts, Instance}; use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt}; use rustc::mir::{self, Body}; use rustc::session::config::DebugInfo; -use rustc_target::abi::call::{FnType, PassMode}; +use rustc_target::abi::call::{FnType, PassMode, IgnoreMode}; use rustc_target::abi::{Variants, VariantIdx}; use crate::base; use crate::debuginfo::{self, VariableAccess, VariableKind, FunctionDebugContext}; @@ -13,8 +13,8 @@ use syntax::symbol::kw; use std::iter; -use rustc_index::bit_set::BitSet; -use rustc_index::vec::IndexVec; +use rustc_data_structures::bit_set::BitSet; +use rustc_data_structures::indexed_vec::IndexVec; use self::analyze::CleanupKind; use self::place::PlaceRef; @@ -30,7 +30,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { debug_context: FunctionDebugContext, - llfn: Bx::Function, + llfn: Bx::Value, cx: &'a Bx::CodegenCx, @@ -81,6 +81,10 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// Debug information for MIR scopes. scopes: IndexVec>, + + /// If this function is a C-variadic function, this contains the `PlaceRef` of the + /// "spoofed" `VaListImpl`. + va_list_ref: Option>, } impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { @@ -183,7 +187,7 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, - llfn: Bx::Function, + llfn: Bx::Value, mir: &'a Body<'tcx>, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, @@ -200,8 +204,6 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx.set_personality_fn(cx.eh_personality()); } - bx.sideeffect(); - let cleanup_kinds = analyze::cleanup_kinds(&mir); // Allocate a `Block` for every basic block, except // the start block, if nothing loops back to it. @@ -234,13 +236,18 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( scopes, locals: IndexVec::new(), debug_context, + va_list_ref: None, }; let memory_locals = analyze::non_ssa_locals(&fx); // Allocate variable and temp allocas fx.locals = { - let args = arg_local_refs(&mut bx, &fx, &memory_locals); + // FIXME(dlrobertson): This is ugly. Find a better way of getting the `PlaceRef` or + // `LocalRef` from `arg_local_refs` + let mut va_list_ref = None; + let args = arg_local_refs(&mut bx, &fx, &memory_locals, &mut va_list_ref); + fx.va_list_ref = va_list_ref; let mut allocate_local = |local| { let decl = &mir.local_decls[local]; @@ -419,6 +426,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, fx: &FunctionCx<'a, 'tcx, Bx>, memory_locals: &BitSet, + va_list_ref: &mut Option>, ) -> Vec> { let mir = fx.mir; let tcx = fx.cx.tcx(); @@ -433,6 +441,15 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( None }; + // Store the index of the last argument. This is used to + // call va_start on the va_list instead of attempting + // to store_fn_arg. + let last_arg_idx = if fx.fn_ty.args.is_empty() { + None + } else { + Some(fx.fn_ty.args.len() - 1) + }; + mir.args_iter().enumerate().map(|(arg_index, local)| { let arg_decl = &mir.local_decls[local]; @@ -486,31 +503,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( return LocalRef::Place(place); } - if fx.fn_ty.c_variadic && arg_index == fx.fn_ty.args.len() { - let arg_ty = fx.monomorphize(&arg_decl.ty); - - let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); - bx.set_var_name(va_list.llval, name); - bx.va_start(va_list.llval); - - arg_scope.map(|scope| { - let variable_access = VariableAccess::DirectVariable { - alloca: va_list.llval - }; - bx.declare_local( - &fx.debug_context, - arg_decl.name.unwrap_or(kw::Invalid), - va_list.layout.ty, - scope, - variable_access, - VariableKind::ArgumentVariable(arg_index + 1), - DUMMY_SP - ); - }); - - return LocalRef::Place(va_list); - } - let arg = &fx.fn_ty.args[idx]; idx += 1; if arg.pad.is_some() { @@ -523,9 +515,10 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // of putting everything in allocas just so we can use llvm.dbg.declare. let local = |op| LocalRef::Operand(Some(op)); match arg.mode { - PassMode::Ignore => { + PassMode::Ignore(IgnoreMode::Zst) => { return local(OperandRef::new_zst(bx, arg.layout)); } + PassMode::Ignore(IgnoreMode::CVarArgs) => {} PassMode::Direct(_) => { let llarg = bx.get_param(llarg_idx); bx.set_var_name(llarg, &name); @@ -575,7 +568,22 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } else { let tmp = PlaceRef::alloca(bx, arg.layout); bx.set_var_name(tmp.llval, name); - bx.store_fn_arg(arg, &mut llarg_idx, tmp); + 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, + None => bug!("`va_list` lang item required for C-variadic functions"), + }; + match arg_decl.ty.kind { + ty::Adt(def, _) if def.did == va_list_did => { + // Call `va_start` on the spoofed `VaListImpl`. + bx.va_start(tmp.llval); + *va_list_ref = Some(tmp); + }, + _ => bug!("last argument of variadic function is not a `va_list`") + } + } else { + bx.store_fn_arg(arg, &mut llarg_idx, tmp); + } tmp }; let upvar_debuginfo = &mir.__upvar_debuginfo_codegen_only_do_not_use; @@ -617,8 +625,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }; let (def_id, upvar_substs) = match closure_layout.ty.kind { - ty::Closure(def_id, substs) => (def_id, - UpvarSubsts::Closure(substs)), + ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)), ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)), _ => bug!("upvar debuginfo with non-closure arg0 type `{}`", closure_layout.ty) }; @@ -638,7 +645,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ty::Generator(def_id, substs, _) => (def_id, substs), _ => bug!("generator layout without generator substs"), }; - let state_tys = gen_substs.as_generator().state_tys(def_id, tcx); + let state_tys = gen_substs.state_tys(def_id, tcx); generator_layout.variant_fields.iter() .zip(state_tys) diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index ba5e47aeede1b..daa25b2ea0591 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -79,7 +79,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { ConstValue::Unevaluated(..) => bug!("unevaluated constant in `OperandRef::from_const`"), ConstValue::Param(_) => bug!("encountered a ConstValue::Param in codegen"), ConstValue::Infer(_) => bug!("encountered a ConstValue::Infer in codegen"), - ConstValue::Bound(..) => bug!("encountered a ConstValue::Bound in codegen"), ConstValue::Placeholder(_) => bug!("encountered a ConstValue::Placeholder in codegen"), ConstValue::Scalar(x) => { let scalar = match layout.abi { diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 1d1bc2a81a2ca..2d97f828f073d 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -394,8 +394,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // Statically compute the offset if we can, otherwise just use the element size, // as this will yield the lowest alignment. let layout = self.layout.field(bx, 0); - let offset = if let Some(llindex) = bx.const_to_opt_uint(llindex) { - layout.size.checked_mul(llindex, bx).unwrap_or(layout.size) + let offset = if bx.is_const_integral(llindex) { + layout.size.checked_mul(bx.const_to_uint(llindex), bx).unwrap_or(layout.size) } else { layout.size }; diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 1608f222bc614..9b69383b455cf 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -10,6 +10,7 @@ use syntax::source_map::{DUMMY_SP, Span}; use crate::base; use crate::MemFlags; +use crate::callee; use crate::common::{self, RealPredicate, IntPredicate}; use crate::traits::*; @@ -94,7 +95,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let size = bx.const_usize(dest.layout.size.bytes()); // Use llvm.memset.p0i8.* to initialize all zero arrays - if bx.cx().const_to_opt_uint(v) == Some(0) { + if bx.cx().is_const_integral(v) && bx.cx().const_to_uint(v) == 0 { let fill = bx.cx().const_u8(0); bx.memset(start, fill, size, dest.align, MemFlags::empty()); return bx; @@ -189,15 +190,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bug!("reifying a fn ptr that requires const arguments"); } OperandValue::Immediate( - bx.get_fn_addr( - ty::Instance::resolve_for_fn_ptr( - bx.tcx(), - ty::ParamEnv::reveal_all(), - def_id, - substs - ).unwrap() - ) - ) + callee::resolve_and_get_fn(bx.cx(), def_id, substs)) } _ => { bug!("{} cannot be reified to a fn ptr", operand.layout.ty) @@ -208,11 +201,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match operand.layout.ty.kind { ty::Closure(def_id, substs) => { let instance = Instance::resolve_closure( - bx.cx().tcx(), - def_id, - substs, - ty::ClosureKind::FnOnce); - OperandValue::Immediate(bx.cx().get_fn_addr(instance)) + bx.cx().tcx(), def_id, substs, ty::ClosureKind::FnOnce); + OperandValue::Immediate(bx.cx().get_fn(instance)) } _ => { bug!("{} cannot be cast to a fn ptr", operand.layout.ty) @@ -495,7 +485,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }; let instance = ty::Instance::mono(bx.tcx(), def_id); - let r = bx.cx().get_fn_addr(instance); + let r = bx.cx().get_fn(instance); let call = bx.call(r, &[llsize, llalign], None); let val = bx.pointercast(call, llty_ptr); @@ -530,7 +520,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) -> Bx::Value { // ZST are passed as operands and require special handling // because codegen_place() panics if Local is operand. - if let Some(index) = place.as_local() { + if let mir::Place { + base: mir::PlaceBase::Local(index), + projection: box [], + } = *place { if let LocalRef::Operand(Some(op)) = self.locals[index] { if let ty::Array(_, n) = op.layout.ty.kind { let n = n.eval_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all()); @@ -553,6 +546,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) -> Bx::Value { let is_float = input_ty.is_floating_point(); let is_signed = input_ty.is_signed(); + let is_unit = input_ty.is_unit(); match op { mir::BinOp::Add => if is_float { bx.fadd(lhs, rhs) @@ -590,7 +584,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::BinOp::Shl => common::build_unchecked_lshift(bx, lhs, rhs), mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs), mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt | - mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_float { + mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_unit { + bx.cx().const_bool(match op { + mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt => false, + mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => true, + _ => unreachable!() + }) + } else if is_float { bx.fcmp( base::bin_op_to_fcmp_predicate(op.to_hir_binop()), lhs, rhs diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index 43d5c2570b705..dab7dfc041751 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -17,8 +17,11 @@ 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(box(ref place, ref rvalue)) => { - if let Some(index) = place.as_local() { - match self.locals[index] { + if let mir::Place { + base: mir::PlaceBase::Local(index), + projection: box [], + } = place { + match self.locals[*index] { LocalRef::Place(cg_dest) => { self.codegen_rvalue(bx, cg_dest, rvalue) } @@ -27,7 +30,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } LocalRef::Operand(None) => { let (mut bx, operand) = self.codegen_rvalue_operand(bx, rvalue); - if let Some(name) = self.mir.local_decls[index].name { + if let Some(name) = self.mir.local_decls[*index].name { match operand.val { OperandValue::Ref(x, ..) | OperandValue::Immediate(x) => { @@ -41,7 +44,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } - self.locals[index] = LocalRef::Operand(Some(operand)); + self.locals[*index] = LocalRef::Operand(Some(operand)); bx } LocalRef::Operand(Some(op)) => { diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index 1fff740d7403f..cb197f51460a1 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -9,13 +9,11 @@ use rustc::ty::TyCtxt; use rustc_codegen_utils::codegen_backend::CodegenBackend; use std::sync::Arc; use std::sync::mpsc; -use syntax_expand::allocator::AllocatorKind; -use syntax_pos::symbol::Symbol; +use syntax::ext::allocator::AllocatorKind; +use syntax_pos::symbol::InternedString; pub trait BackendTypes { type Value: CodegenObject; - type Function: CodegenObject; - type BasicBlock: Copy; type Type: CodegenObject; type Funclet; @@ -50,7 +48,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se fn compile_codegen_unit( &self, tcx: TyCtxt<'_>, - cgu_name: Symbol, + cgu_name: InternedString, tx_to_llvm_workers: &mpsc::Sender>, ); // If find_features is true this won't access `sess.crate_types` by assuming diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 62b5bcbb6c9dc..1886701fb3a88 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -34,7 +34,7 @@ pub trait BuilderMethods<'a, 'tcx>: + HasTargetSpec { - fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Function, name: &'b str) -> Self; + fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Value, name: &'b str) -> Self; fn with_cx(cx: &'a Self::CodegenCx) -> Self; fn build_sibling_block(&self, name: &str) -> Self; fn cx(&self) -> &Self::CodegenCx; diff --git a/src/librustc_codegen_ssa/traits/consts.rs b/src/librustc_codegen_ssa/traits/consts.rs index 95ada60fae08d..e7ce03f183619 100644 --- a/src/librustc_codegen_ssa/traits/consts.rs +++ b/src/librustc_codegen_ssa/traits/consts.rs @@ -21,9 +21,11 @@ pub trait ConstMethods<'tcx>: BackendTypes { fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value; - fn const_to_opt_uint(&self, v: Self::Value) -> Option; + fn const_to_uint(&self, v: Self::Value) -> u64; fn const_to_opt_u128(&self, v: Self::Value, sign_ext: bool) -> Option; + fn is_const_integral(&self, v: Self::Value) -> bool; + fn scalar_to_backend( &self, cv: Scalar, diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs index 989e6cf9dcaf1..9c16b864ef21d 100644 --- a/src/librustc_codegen_ssa/traits/debuginfo.rs +++ b/src/librustc_codegen_ssa/traits/debuginfo.rs @@ -3,7 +3,7 @@ use crate::debuginfo::{FunctionDebugContext, MirDebugScope, VariableAccess, Vari use rustc::hir::def_id::CrateNum; use rustc::mir; use rustc::ty::{self, Ty, Instance}; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use syntax::ast::Name; use syntax_pos::{SourceFile, Span}; @@ -20,7 +20,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes { &self, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, - llfn: Self::Function, + llfn: Self::Value, mir: &mir::Body<'_>, ) -> FunctionDebugContext; diff --git a/src/librustc_codegen_ssa/traits/declare.rs b/src/librustc_codegen_ssa/traits/declare.rs index cd42044e48df8..624a982b619ee 100644 --- a/src/librustc_codegen_ssa/traits/declare.rs +++ b/src/librustc_codegen_ssa/traits/declare.rs @@ -17,13 +17,13 @@ pub trait DeclareMethods<'tcx>: BackendTypes { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - fn declare_cfn(&self, name: &str, fn_type: Self::Type) -> Self::Function; + fn declare_cfn(&self, name: &str, fn_type: Self::Type) -> Self::Value; /// Declare a Rust function. /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - fn declare_fn(&self, name: &str, sig: ty::PolyFnSig<'tcx>) -> Self::Function; + fn declare_fn(&self, name: &str, sig: ty::PolyFnSig<'tcx>) -> Self::Value; /// Declare a global with an intention to define it. /// diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs index 2c484084c4a20..7c79cd6021031 100644 --- a/src/librustc_codegen_ssa/traits/intrinsic.rs +++ b/src/librustc_codegen_ssa/traits/intrinsic.rs @@ -20,7 +20,6 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes { fn abort(&mut self); fn assume(&mut self, val: Self::Value); fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value; - fn sideeffect(&mut self); /// Trait method used to inject `va_start` on the "spoofed" `VaListImpl` in /// Rust defined C-variadic functions. fn va_start(&mut self, val: Self::Value) -> Self::Value; diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs index 658ddd0028076..46c88a6113ebe 100644 --- a/src/librustc_codegen_ssa/traits/misc.rs +++ b/src/librustc_codegen_ssa/traits/misc.rs @@ -11,14 +11,14 @@ pub trait MiscMethods<'tcx>: BackendTypes { &self, ) -> &RefCell, Option>), Self::Value>>; fn check_overflow(&self) -> bool; - fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function; - fn get_fn_addr(&self, instance: Instance<'tcx>) -> Self::Value; + fn instances(&self) -> &RefCell, Self::Value>>; + fn get_fn(&self, instance: Instance<'tcx>) -> Self::Value; fn eh_personality(&self) -> Self::Value; fn eh_unwind_resume(&self) -> Self::Value; fn sess(&self) -> &Session; fn codegen_unit(&self) -> &Arc>; fn used_statics(&self) -> &RefCell>; - fn set_frame_pointer_elimination(&self, llfn: Self::Function); - fn apply_target_cpu_attr(&self, llfn: Self::Function); + fn set_frame_pointer_elimination(&self, llfn: Self::Value); + fn apply_target_cpu_attr(&self, llfn: Self::Value); fn create_used_variable(&self); } diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs index 4318ef16494a1..efe4a25570104 100644 --- a/src/librustc_codegen_ssa/traits/mod.rs +++ b/src/librustc_codegen_ssa/traits/mod.rs @@ -88,7 +88,6 @@ pub trait HasCodegen<'tcx>: type CodegenCx: CodegenMethods<'tcx> + BackendTypes< Value = Self::Value, - Function = Self::Function, BasicBlock = Self::BasicBlock, Type = Self::Type, Funclet = Self::Funclet, diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs index 0e2c3731eae6d..2e3af8431eed0 100644 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ b/src/librustc_codegen_utils/codegen_backend.rs @@ -14,7 +14,7 @@ use rustc::util::common::ErrorReported; use rustc::session::config::{OutputFilenames, PrintRequest}; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; use rustc::dep_graph::DepGraph; pub use rustc_data_structures::sync::MetadataRef; @@ -25,8 +25,9 @@ pub trait CodegenBackend { fn target_features(&self, _sess: &Session) -> Vec { vec![] } fn print_passes(&self) {} fn print_version(&self) {} + fn diagnostics(&self) -> &[(&'static str, &'static str)] { &[] } - fn metadata_loader(&self) -> Box; + fn metadata_loader(&self) -> Box; fn provide(&self, _providers: &mut Providers<'_>); fn provide_extern(&self, _providers: &mut Providers<'_>); fn codegen_crate<'tcx>( diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 66920342ff6ba..1201446afb531 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -18,7 +18,6 @@ extern crate rustc; use rustc::ty::TyCtxt; -use rustc::ty::query::Providers; use rustc::hir::def_id::LOCAL_CRATE; use syntax::symbol::sym; @@ -38,7 +37,3 @@ pub fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { } } } - -pub fn provide(providers: &mut Providers<'_>) { - crate::symbol_names::provide(providers); -} diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index c52c6cfa83c91..7ccd024769f75 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -95,7 +95,7 @@ use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt, Instance}; use rustc::mir::mono::{MonoItem, InstantiationMode}; -use syntax_pos::symbol::Symbol; +use syntax_pos::symbol::InternedString; use log::debug; @@ -112,7 +112,7 @@ pub fn provide(providers: &mut Providers<'_>) { }; } -fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol { +fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> InternedString { let def_id = instance.def_id(); let substs = instance.substs; @@ -123,11 +123,13 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol { if def_id.is_local() { if tcx.plugin_registrar_fn(LOCAL_CRATE) == Some(def_id) { let disambiguator = tcx.sess.local_crate_disambiguator(); - return Symbol::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator)); + return + InternedString::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator)); } if tcx.proc_macro_decls_static(LOCAL_CRATE) == Some(def_id) { let disambiguator = tcx.sess.local_crate_disambiguator(); - return Symbol::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator)); + return + InternedString::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator)); } } @@ -144,22 +146,23 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol { let attrs = tcx.codegen_fn_attrs(def_id); if is_foreign { if let Some(name) = attrs.link_name { - return name; + return name.as_interned_str(); } // Don't mangle foreign items. - return tcx.item_name(def_id); + return tcx.item_name(def_id).as_interned_str(); } - if let Some(name) = attrs.export_name { + if let Some(name) = &attrs.export_name { // Use provided name - return name; + return name.as_interned_str(); } if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { // Don't mangle - return tcx.item_name(def_id); + return tcx.item_name(def_id).as_interned_str(); } + let is_generic = substs.non_erasable_generics().next().is_some(); let avoid_cross_crate_conflicts = // If this is an instance of a generic function, we also hash in @@ -219,5 +222,5 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol { SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate), }; - Symbol::intern(&mangled) + InternedString::intern(&mangled) } diff --git a/src/librustc_codegen_utils/symbol_names/legacy.rs b/src/librustc_codegen_utils/symbol_names/legacy.rs index 601a33a66bb32..277aa2db33a1b 100644 --- a/src/librustc_codegen_utils/symbol_names/legacy.rs +++ b/src/librustc_codegen_utils/symbol_names/legacy.rs @@ -89,7 +89,7 @@ fn get_symbol_hash<'tcx>( def_id, substs ); - let mut hasher = StableHasher::new(); + let mut hasher = StableHasher::::new(); let mut hcx = tcx.create_stable_hashing_context(); record_time(&tcx.sess.perf_stats.symbol_hash_time, || { @@ -132,7 +132,7 @@ fn get_symbol_hash<'tcx>( }); // 64 bits should be enough to avoid collisions. - hasher.finish::() + hasher.finish() } // Follow C++ namespace-mangling style, see @@ -224,8 +224,8 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { ty::Opaque(def_id, substs) | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | - ty::Closure(def_id, substs) | - ty::Generator(def_id, substs, _) => { + ty::Closure(def_id, ty::ClosureSubsts { substs }) | + ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { self.print_def_path(def_id, substs) } _ => self.pretty_print_type(ty), @@ -335,7 +335,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { self.path.finalize_pending_component(); } - self.write_str(&disambiguated_data.data.as_symbol().as_str())?; + self.write_str(&disambiguated_data.data.as_interned_str().as_str())?; Ok(self) } fn path_generic_args( diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs index 55b148fceb217..a63236305dc11 100644 --- a/src/librustc_codegen_utils/symbol_names/v0.rs +++ b/src/librustc_codegen_utils/symbol_names/v0.rs @@ -414,8 +414,8 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { ty::Opaque(def_id, substs) | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | - ty::Closure(def_id, substs) | - ty::Generator(def_id, substs, _) => { + ty::Closure(def_id, ty::ClosureSubsts { substs }) | + ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { self = self.print_def_path(def_id, substs)?; } ty::Foreign(def_id) => { diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 065c8436ae06a..ae3403cf0ce9f 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -20,11 +20,10 @@ graphviz = { path = "../libgraphviz" } cfg-if = "0.1.2" crossbeam-utils = { version = "0.6.5", features = ["nightly"] } stable_deref_trait = "1.0.0" -rayon = { version = "0.3.0", package = "rustc-rayon" } -rayon-core = { version = "0.3.0", package = "rustc-rayon-core" } +rayon = { version = "0.2.0", package = "rustc-rayon" } +rayon-core = { version = "0.2.0", package = "rustc-rayon-core" } rustc-hash = "1.0.1" smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } -rustc_index = { path = "../librustc_index", package = "rustc_index" } [dependencies.parking_lot] version = "0.9" diff --git a/src/librustc_index/bit_set.rs b/src/librustc_data_structures/bit_set.rs similarity index 94% rename from src/librustc_index/bit_set.rs rename to src/librustc_data_structures/bit_set.rs index 9ed5ef5a539a1..fe8ef642430ad 100644 --- a/src/librustc_index/bit_set.rs +++ b/src/librustc_data_structures/bit_set.rs @@ -1,4 +1,4 @@ -use crate::vec::{Idx, IndexVec}; +use crate::indexed_vec::{Idx, IndexVec}; use smallvec::SmallVec; use std::fmt; use std::iter; @@ -13,9 +13,8 @@ pub type Word = u64; pub const WORD_BYTES: usize = mem::size_of::(); pub const WORD_BITS: usize = WORD_BYTES * 8; -/// A fixed-size bitset type with a dense representation. -/// -/// NOTE: Use [`GrowableBitSet`] if you need support for resizing after creation. +/// A fixed-size bitset type with a dense representation. It does not support +/// resizing after creation; use `GrowableBitSet` for that. /// /// `T` is an index type, typically a newtyped `usize` wrapper, but it can also /// just be `usize`. @@ -23,8 +22,6 @@ pub const WORD_BITS: usize = WORD_BYTES * 8; /// All operations that involve an element will panic if the element is equal /// to or greater than the domain size. All operations that involve two bitsets /// will panic if the bitsets have differing domain sizes. -/// -/// [`GrowableBitSet`]: struct.GrowableBitSet.html #[derive(Clone, Eq, PartialEq, RustcDecodable, RustcEncodable)] pub struct BitSet { domain_size: usize, @@ -171,7 +168,11 @@ impl BitSet { /// Iterates over the indices of set bits in a sorted order. #[inline] pub fn iter(&self) -> BitIter<'_, T> { - BitIter::new(&self.words) + BitIter { + cur: None, + iter: self.words.iter().enumerate(), + marker: PhantomData, + } } /// Duplicates the set as a hybrid set. @@ -290,55 +291,26 @@ impl ToString for BitSet { } pub struct BitIter<'a, T: Idx> { - /// A copy of the current word, but with any already-visited bits cleared. - /// (This lets us use `trailing_zeros()` to find the next set bit.) When it - /// is reduced to 0, we move onto the next word. - word: Word, - - /// The offset (measured in bits) of the current word. - offset: usize, - - /// Underlying iterator over the words. - iter: slice::Iter<'a, Word>, - + cur: Option<(Word, usize)>, + iter: iter::Enumerate>, marker: PhantomData } -impl<'a, T: Idx> BitIter<'a, T> { - #[inline] - fn new(words: &'a [Word]) -> BitIter<'a, T> { - // We initialize `word` and `offset` to degenerate values. On the first - // call to `next()` we will fall through to getting the first word from - // `iter`, which sets `word` to the first word (if there is one) and - // `offset` to 0. Doing it this way saves us from having to maintain - // additional state about whether we have started. - BitIter { - word: 0, - offset: std::usize::MAX - (WORD_BITS - 1), - iter: words.iter(), - marker: PhantomData, - } - } -} - impl<'a, T: Idx> Iterator for BitIter<'a, T> { type Item = T; fn next(&mut self) -> Option { loop { - if self.word != 0 { - // Get the position of the next set bit in the current word, - // then clear the bit. - let bit_pos = self.word.trailing_zeros() as usize; - let bit = 1 << bit_pos; - self.word ^= bit; - return Some(T::new(bit_pos + self.offset)) + if let Some((ref mut word, offset)) = self.cur { + let bit_pos = word.trailing_zeros() as usize; + if bit_pos != WORD_BITS { + let bit = 1 << bit_pos; + *word ^= bit; + return Some(T::new(bit_pos + offset)) + } } - // Move onto the next word. `wrapping_add()` is needed to handle - // the degenerate initial value given to `offset` in `new()`. - let word = self.iter.next()?; - self.word = *word; - self.offset = self.offset.wrapping_add(WORD_BITS); + let (i, word) = self.iter.next()?; + self.cur = Some((*word, WORD_BITS * i)); } } } @@ -649,7 +621,7 @@ impl<'a, T: Idx> Iterator for HybridIter<'a, T> { fn next(&mut self) -> Option { match self { - HybridIter::Sparse(sparse) => sparse.next().copied(), + HybridIter::Sparse(sparse) => sparse.next().map(|e| *e), HybridIter::Dense(dense) => dense.next(), } } @@ -879,7 +851,11 @@ impl BitMatrix { pub fn iter(&self, row: R) -> BitIter<'_, C> { assert!(row.index() < self.num_rows); let (start, end) = self.range(row); - BitIter::new(&self.words[start..end]) + BitIter { + cur: None, + iter: self.words[start..end].iter().enumerate(), + marker: PhantomData, + } } /// Returns the number of elements in `row`. diff --git a/src/librustc_index/bit_set/tests.rs b/src/librustc_data_structures/bit_set/tests.rs similarity index 100% rename from src/librustc_index/bit_set/tests.rs rename to src/librustc_data_structures/bit_set/tests.rs diff --git a/src/librustc_data_structures/fingerprint.rs b/src/librustc_data_structures/fingerprint.rs index b43df6045d6aa..c8012bb942461 100644 --- a/src/librustc_data_structures/fingerprint.rs +++ b/src/librustc_data_structures/fingerprint.rs @@ -76,7 +76,7 @@ impl ::std::fmt::Display for Fingerprint { impl stable_hasher::StableHasherResult for Fingerprint { #[inline] - fn finish(hasher: stable_hasher::StableHasher) -> Self { + fn finish(hasher: stable_hasher::StableHasher) -> Self { let (_0, _1) = hasher.finalize(); Fingerprint(_0, _1) } diff --git a/src/librustc_data_structures/graph/dominators/mod.rs b/src/librustc_data_structures/graph/dominators/mod.rs index 444463c08e557..41e6b72953e83 100644 --- a/src/librustc_data_structures/graph/dominators/mod.rs +++ b/src/librustc_data_structures/graph/dominators/mod.rs @@ -4,7 +4,7 @@ //! Rice Computer Science TS-06-33870 //! -use rustc_index::vec::{Idx, IndexVec}; +use super::super::indexed_vec::{Idx, IndexVec}; use super::iterate::reverse_post_order; use super::ControlFlowGraph; @@ -17,7 +17,7 @@ pub fn dominators(graph: &G) -> Dominators { dominators_given_rpo(graph, &rpo) } -fn dominators_given_rpo( +pub fn dominators_given_rpo( graph: &G, rpo: &[G::Node], ) -> Dominators { @@ -43,12 +43,14 @@ fn dominators_given_rpo( let mut new_idom = None; for pred in graph.predecessors(node) { if immediate_dominators[pred].is_some() { + // (*) // (*) dominators for `pred` have been calculated - new_idom = Some(if let Some(new_idom) = new_idom { - intersect(&post_order_rank, &immediate_dominators, new_idom, pred) - } else { - pred - }); + new_idom = intersect_opt( + &post_order_rank, + &immediate_dominators, + new_idom, + Some(pred), + ); } } @@ -65,6 +67,19 @@ fn dominators_given_rpo( } } +fn intersect_opt( + post_order_rank: &IndexVec, + immediate_dominators: &IndexVec>, + node1: Option, + node2: Option, +) -> Option { + match (node1, node2) { + (None, None) => None, + (Some(n), None) | (None, Some(n)) => Some(n), + (Some(n1), Some(n2)) => Some(intersect(post_order_rank, immediate_dominators, n1, n2)), + } +} + fn intersect( post_order_rank: &IndexVec, immediate_dominators: &IndexVec>, diff --git a/src/librustc_data_structures/graph/implementation/mod.rs b/src/librustc_data_structures/graph/implementation/mod.rs index 9fdcea6df88c5..d2699004c81d8 100644 --- a/src/librustc_data_structures/graph/implementation/mod.rs +++ b/src/librustc_data_structures/graph/implementation/mod.rs @@ -20,7 +20,7 @@ //! the field `next_edge`). Each of those fields is an array that should //! be indexed by the direction (see the type `Direction`). -use rustc_index::bit_set::BitSet; +use crate::bit_set::BitSet; use crate::snapshot_vec::{SnapshotVec, SnapshotVecDelegate}; use std::fmt::Debug; use std::usize; @@ -60,10 +60,10 @@ impl SnapshotVecDelegate for Edge { fn reverse(_: &mut Vec>, _: ()) {} } -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub struct NodeIndex(pub usize); -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub struct EdgeIndex(pub usize); pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX); @@ -303,11 +303,11 @@ pub struct AdjacentEdges<'g, N, E> { impl<'g, N: Debug, E: Debug> AdjacentEdges<'g, N, E> { fn targets(self) -> impl Iterator + 'g { - self.map(|(_, edge)| edge.target) + self.into_iter().map(|(_, edge)| edge.target) } fn sources(self) -> impl Iterator + 'g { - self.map(|(_, edge)| edge.source) + self.into_iter().map(|(_, edge)| edge.source) } } diff --git a/src/librustc_data_structures/graph/iterate/mod.rs b/src/librustc_data_structures/graph/iterate/mod.rs index e268b28174474..cbf6a0a3c03a0 100644 --- a/src/librustc_data_structures/graph/iterate/mod.rs +++ b/src/librustc_data_structures/graph/iterate/mod.rs @@ -1,6 +1,6 @@ -use rustc_index::vec::IndexVec; +use super::super::indexed_vec::IndexVec; use super::{DirectedGraph, WithNumNodes, WithSuccessors, WithStartNode}; -use rustc_index::bit_set::BitSet; +use crate::bit_set::BitSet; #[cfg(test)] mod tests; diff --git a/src/librustc_data_structures/graph/mod.rs b/src/librustc_data_structures/graph/mod.rs index 37335799d19af..0a607659f3e24 100644 --- a/src/librustc_data_structures/graph/mod.rs +++ b/src/librustc_data_structures/graph/mod.rs @@ -1,4 +1,4 @@ -use rustc_index::vec::Idx; +use super::indexed_vec::Idx; pub mod dominators; pub mod implementation; diff --git a/src/librustc_data_structures/graph/scc/mod.rs b/src/librustc_data_structures/graph/scc/mod.rs index c214f66cd15cd..23a1a2a90a4d5 100644 --- a/src/librustc_data_structures/graph/scc/mod.rs +++ b/src/librustc_data_structures/graph/scc/mod.rs @@ -6,7 +6,7 @@ use crate::fx::FxHashSet; use crate::graph::{DirectedGraph, WithNumNodes, WithNumEdges, WithSuccessors, GraphSuccessors}; use crate::graph::vec_graph::VecGraph; -use rustc_index::vec::{Idx, IndexVec}; +use crate::indexed_vec::{Idx, IndexVec}; use std::ops::Range; #[cfg(test)] diff --git a/src/librustc_data_structures/graph/vec_graph/mod.rs b/src/librustc_data_structures/graph/vec_graph/mod.rs index aad5944dcd0be..19c61f2680d1d 100644 --- a/src/librustc_data_structures/graph/vec_graph/mod.rs +++ b/src/librustc_data_structures/graph/vec_graph/mod.rs @@ -1,4 +1,4 @@ -use rustc_index::vec::{Idx, IndexVec}; +use crate::indexed_vec::{Idx, IndexVec}; use crate::graph::{DirectedGraph, WithNumNodes, WithNumEdges, WithSuccessors, GraphSuccessors}; #[cfg(test)] diff --git a/src/librustc_index/vec.rs b/src/librustc_data_structures/indexed_vec.rs similarity index 100% rename from src/librustc_index/vec.rs rename to src/librustc_data_structures/indexed_vec.rs diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 474a42644d915..d6e9c479c9b8d 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -68,12 +68,14 @@ pub mod macros; pub mod svh; pub mod base_n; pub mod binary_search_util; +pub mod bit_set; pub mod box_region; pub mod const_cstr; pub mod flock; pub mod fx; pub mod stable_map; pub mod graph; +pub mod indexed_vec; pub mod jobserver; pub mod obligation_forest; pub mod owning_ref; diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index 958ab617cb315..1c7109fe500e0 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -138,7 +138,7 @@ pub struct ObligationForest { /// call to `compress`. /// /// `usize` indices are used here and throughout this module, rather than - /// `rustc_index::newtype_index!` indices, because this code is hot enough that the + /// `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>, @@ -151,8 +151,9 @@ pub struct ObligationForest { /// comments in `process_obligation` for details. active_cache: FxHashMap, - /// A vector reused in compress(), to avoid allocating new vectors. - node_rewrites: RefCell>, + /// A scratch vector reused in various operations, to avoid allocating new + /// vectors. + scratch: RefCell>, obligation_tree_id_generator: ObligationTreeIdGenerator, @@ -234,6 +235,10 @@ enum NodeState { /// This obligation was resolved to an error. Error nodes are /// removed from the vector by the compression step. Error, + + /// This is a temporary state used in DFS loops to detect cycles, + /// it should not exist outside of these DFSes. + OnDfsStack, } #[derive(Debug)] @@ -274,7 +279,7 @@ impl ObligationForest { nodes: vec![], done_cache: Default::default(), active_cache: Default::default(), - node_rewrites: RefCell::new(vec![]), + scratch: RefCell::new(vec![]), obligation_tree_id_generator: (0..).map(ObligationTreeId), error_cache: Default::default(), } @@ -300,10 +305,9 @@ impl ObligationForest { match self.active_cache.entry(obligation.as_predicate().clone()) { Entry::Occupied(o) => { - let index = *o.get(); debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!", - obligation, parent, index); - let node = &mut self.nodes[index]; + obligation, parent, o.get()); + let node = &mut self.nodes[*o.get()]; if let Some(parent_index) = parent { // If the node is already in `active_cache`, it has already // had its chance to be marked with a parent. So if it's @@ -338,8 +342,7 @@ impl ObligationForest { if already_failed { Err(()) } else { - let new_index = self.nodes.len(); - v.insert(new_index); + v.insert(self.nodes.len()); self.nodes.push(Node::new(parent, obligation, obligation_tree_id)); Ok(()) } @@ -349,16 +352,15 @@ impl ObligationForest { /// Converts all remaining obligations to the given error. pub fn to_errors(&mut self, error: E) -> Vec> { - let errors = self.nodes.iter().enumerate() - .filter(|(_index, node)| node.state.get() == NodeState::Pending) - .map(|(index, _node)| { - Error { + let mut errors = vec![]; + for (index, node) in self.nodes.iter().enumerate() { + if let NodeState::Pending = node.state.get() { + errors.push(Error { error: error.clone(), backtrace: self.error_at(index), - } - }) - .collect(); - + }); + } + } let successful_obligations = self.compress(DoCompleted::Yes); assert!(successful_obligations.unwrap().is_empty()); errors @@ -368,14 +370,15 @@ impl ObligationForest { pub fn map_pending_obligations(&self, f: F) -> Vec

where F: Fn(&O) -> P { - self.nodes.iter() - .filter(|node| node.state.get() == NodeState::Pending) - .map(|node| f(&node.obligation)) + self.nodes + .iter() + .filter(|n| n.state.get() == NodeState::Pending) + .map(|n| f(&n.obligation)) .collect() } - fn insert_into_error_cache(&mut self, index: usize) { - let node = &self.nodes[index]; + 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() @@ -405,10 +408,10 @@ impl ObligationForest { // `self.active_cache`. This means that `self.active_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. - if node.state.get() != NodeState::Pending { - continue; - } - let result = processor.process_obligation(&mut node.obligation); + let result = match node.state.get() { + NodeState::Pending => processor.process_obligation(&mut node.obligation), + _ => continue + }; debug!("process_obligations: node {} got result {:?}", index, result); @@ -473,7 +476,8 @@ impl ObligationForest { fn process_cycles

(&self, processor: &mut P) where P: ObligationProcessor { - let mut stack = vec![]; + let mut stack = self.scratch.replace(vec![]); + debug_assert!(stack.is_empty()); debug!("process_cycles()"); @@ -481,45 +485,55 @@ impl ObligationForest { // For some benchmarks this state test is extremely // hot. It's a win to handle the no-op cases immediately to avoid // the cost of the function call. - if node.state.get() == NodeState::Success { - self.find_cycles_from_node(&mut stack, processor, index); + match node.state.get() { + // Match arms are in order of frequency. Pending, Success and + // Waiting dominate; the others are rare. + NodeState::Pending => {}, + NodeState::Success => self.find_cycles_from_node(&mut stack, processor, index), + NodeState::Waiting | NodeState::Done | NodeState::Error => {}, + NodeState::OnDfsStack => self.find_cycles_from_node(&mut stack, processor, index), } } debug!("process_cycles: complete"); debug_assert!(stack.is_empty()); + self.scratch.replace(stack); } fn find_cycles_from_node

(&self, stack: &mut Vec, processor: &mut P, index: usize) where P: ObligationProcessor { let node = &self.nodes[index]; - if node.state.get() == NodeState::Success { - match stack.iter().rposition(|&n| n == index) { - None => { - stack.push(index); - for &index in node.dependents.iter() { - self.find_cycles_from_node(stack, processor, index); - } - stack.pop(); - node.state.set(NodeState::Done); - } - Some(rpos) => { - // Cycle detected. - processor.process_backedge( - stack[rpos..].iter().map(GetObligation(&self.nodes)), - PhantomData - ); + match node.state.get() { + NodeState::OnDfsStack => { + let rpos = stack.iter().rposition(|&n| n == index).unwrap(); + processor.process_backedge(stack[rpos..].iter().map(GetObligation(&self.nodes)), + PhantomData); + } + NodeState::Success => { + node.state.set(NodeState::OnDfsStack); + stack.push(index); + 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 + // will get to it when they are all processed. } - } + NodeState::Done | NodeState::Error => { + // 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(&self, mut index: usize) -> Vec { - let mut error_stack: Vec = vec![]; + let mut error_stack = self.scratch.replace(vec![]); let mut trace = vec![]; loop { @@ -540,12 +554,15 @@ impl ObligationForest { while let Some(index) = error_stack.pop() { let node = &self.nodes[index]; - if node.state.get() != NodeState::Error { - node.state.set(NodeState::Error); - error_stack.extend(node.dependents.iter()); + match node.state.get() { + NodeState::Error => continue, + _ => node.state.set(NodeState::Error), } + + error_stack.extend(node.dependents.iter()); } + self.scratch.replace(error_stack); trace } @@ -553,19 +570,7 @@ impl ObligationForest { #[inline(always)] fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node) { for &index in node.dependents.iter() { - let node = &self.nodes[index]; - match node.state.get() { - NodeState::Waiting | NodeState::Error => {} - NodeState::Success => { - node.state.set(NodeState::Waiting); - // This call site is cold. - self.uninlined_mark_neighbors_as_waiting_from(node); - } - NodeState::Pending | NodeState::Done => { - // This call site is cold. - self.uninlined_mark_neighbors_as_waiting_from(node); - } - } + self.mark_as_waiting_from(&self.nodes[index]); } } @@ -591,28 +596,37 @@ impl ObligationForest { } } - /// Compresses the vector, removing all popped nodes. This adjusts the - /// indices and hence invalidates any outstanding indices. + fn mark_as_waiting_from(&self, node: &Node) { + match node.state.get() { + NodeState::Waiting | NodeState::Error | NodeState::OnDfsStack => return, + NodeState::Success => node.state.set(NodeState::Waiting), + NodeState::Pending | NodeState::Done => {}, + } + + // This call site is cold. + self.uninlined_mark_neighbors_as_waiting_from(node); + } + + /// Compresses the vector, removing all popped nodes. This adjusts + /// the indices and hence invalidates any outstanding + /// indices. Cannot be used during a transaction. /// /// Beforehand, all nodes must be marked as `Done` and no cycles /// on these nodes may be present. This is done by e.g., `process_cycles`. #[inline(never)] fn compress(&mut self, do_completed: DoCompleted) -> Option> { - let orig_nodes_len = self.nodes.len(); - let mut node_rewrites: Vec<_> = self.node_rewrites.replace(vec![]); - debug_assert!(node_rewrites.is_empty()); - node_rewrites.extend(0..orig_nodes_len); + let nodes_len = self.nodes.len(); + let mut node_rewrites: Vec<_> = self.scratch.replace(vec![]); + node_rewrites.extend(0..nodes_len); let mut dead_nodes = 0; - let mut removed_done_obligations: Vec = vec![]; - // Now move all Done/Error nodes to the end, preserving the order of - // the Pending/Waiting nodes. + // Now move all popped nodes to the end. Try to keep the order. // // LOOP INVARIANT: // 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..orig_nodes_len { + for index in 0..self.nodes.len() { let node = &self.nodes[index]; match node.state.get() { NodeState::Pending | NodeState::Waiting => { @@ -623,7 +637,7 @@ impl ObligationForest { } NodeState::Done => { // This lookup can fail because the contents of - // `self.active_cache` are not guaranteed to match those of + // `self.active_cache` is not guaranteed to match those of // `self.nodes`. See the comment in `process_obligation` // for more details. if let Some((predicate, _)) = @@ -633,11 +647,7 @@ impl ObligationForest { } else { self.done_cache.insert(node.obligation.as_predicate().clone()); } - if do_completed == DoCompleted::Yes { - // Extract the success stories. - removed_done_obligations.push(node.obligation.clone()); - } - node_rewrites[index] = orig_nodes_len; + node_rewrites[index] = nodes_len; dead_nodes += 1; } NodeState::Error => { @@ -645,38 +655,53 @@ impl ObligationForest { // tests must come up with a different type on every type error they // check against. self.active_cache.remove(node.obligation.as_predicate()); - self.insert_into_error_cache(index); - node_rewrites[index] = orig_nodes_len; + node_rewrites[index] = nodes_len; dead_nodes += 1; + self.insert_into_error_cache(index); } - NodeState::Success => unreachable!() + NodeState::OnDfsStack | NodeState::Success => unreachable!() } } - if dead_nodes > 0 { - // Remove the dead nodes and rewrite indices. - self.nodes.truncate(orig_nodes_len - dead_nodes); - self.apply_rewrites(&node_rewrites); + // No compression needed. + if dead_nodes == 0 { + node_rewrites.truncate(0); + self.scratch.replace(node_rewrites); + return if do_completed == DoCompleted::Yes { Some(vec![]) } else { None }; } - node_rewrites.truncate(0); - self.node_rewrites.replace(node_rewrites); - - if do_completed == DoCompleted::Yes { - Some(removed_done_obligations) + // 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()) + .flat_map(|node| { + match node.state.get() { + NodeState::Error => None, + NodeState::Done => Some(node.obligation), + _ => unreachable!() + } + }) + .collect()) } else { + self.nodes.truncate(self.nodes.len() - dead_nodes); None - } + }; + self.apply_rewrites(&node_rewrites); + + node_rewrites.truncate(0); + self.scratch.replace(node_rewrites); + + successful } fn apply_rewrites(&mut self, node_rewrites: &[usize]) { - let orig_nodes_len = node_rewrites.len(); + let nodes_len = node_rewrites.len(); for node in &mut self.nodes { let mut i = 0; while i < node.dependents.len() { let new_index = node_rewrites[node.dependents[i]]; - if new_index >= orig_nodes_len { + if new_index >= nodes_len { node.dependents.swap_remove(i); if i == 0 && node.has_parent { // We just removed the parent. @@ -693,7 +718,7 @@ impl ObligationForest { // removal of nodes within `compress` can fail. See above. self.active_cache.retain(|_predicate, index| { let new_index = node_rewrites[*index]; - if new_index >= orig_nodes_len { + if new_index >= nodes_len { false } else { *index = new_index; diff --git a/src/librustc_data_structures/obligation_forest/tests.rs b/src/librustc_data_structures/obligation_forest/tests.rs index 54b6f6d0adc6c..e20466572a26f 100644 --- a/src/librustc_data_structures/obligation_forest/tests.rs +++ b/src/librustc_data_structures/obligation_forest/tests.rs @@ -116,9 +116,7 @@ fn push_pop() { _ => unreachable!(), } }, |_| {}), DoCompleted::Yes); - let mut ok = ok.unwrap(); - ok.sort(); - assert_eq!(ok, vec!["A.1", "A.3", "A.3.i"]); + assert_eq!(ok.unwrap(), vec!["A.3", "A.1", "A.3.i"]); assert_eq!(err, vec![Error { error: "A is for apple", @@ -134,9 +132,7 @@ fn push_pop() { _ => panic!("unexpected obligation {:?}", obligation), } }, |_| {}), DoCompleted::Yes); - let mut ok = ok.unwrap(); - ok.sort(); - assert_eq!(ok, vec!["D.2", "D.2.i"]); + assert_eq!(ok.unwrap(), vec!["D.2.i", "D.2"]); assert_eq!(err, vec![Error { error: "D is for dumb", @@ -176,9 +172,7 @@ fn success_in_grandchildren() { _ => unreachable!(), } }, |_| {}), DoCompleted::Yes); - let mut ok = ok.unwrap(); - ok.sort(); - assert_eq!(ok, vec!["A.1", "A.3"]); + assert_eq!(ok.unwrap(), vec!["A.3", "A.1"]); assert!(err.is_empty()); let Outcome { completed: ok, errors: err, .. } = @@ -199,9 +193,7 @@ fn success_in_grandchildren() { _ => unreachable!(), } }, |_| {}), DoCompleted::Yes); - let mut ok = ok.unwrap(); - ok.sort(); - assert_eq!(ok, vec!["A", "A.2", "A.2.i", "A.2.i.a"]); + assert_eq!(ok.unwrap(), vec!["A.2.i.a", "A.2.i", "A.2", "A"]); assert!(err.is_empty()); let Outcome { completed: ok, errors: err, .. } = @@ -269,9 +261,7 @@ fn diamond() { } }, |_|{}), DoCompleted::Yes); assert_eq!(d_count, 1); - let mut ok = ok.unwrap(); - ok.sort(); - assert_eq!(ok, vec!["A", "A.1", "A.2", "D"]); + assert_eq!(ok.unwrap(), vec!["D", "A.2", "A.1", "A"]); assert_eq!(err.len(), 0); let errors = forest.to_errors(()); @@ -333,9 +323,7 @@ fn done_dependency() { _ => unreachable!(), } }, |_|{}), DoCompleted::Yes); - let mut ok = ok.unwrap(); - ok.sort(); - assert_eq!(ok, vec!["A: Sized", "B: Sized", "C: Sized"]); + assert_eq!(ok.unwrap(), vec!["C: Sized", "B: Sized", "A: Sized"]); assert_eq!(err.len(), 0); forest.register_obligation("(A,B,C): Sized"); @@ -373,9 +361,7 @@ fn orphan() { _ => unreachable!(), } }, |_|{}), DoCompleted::Yes); - let mut ok = ok.unwrap(); - ok.sort(); - assert_eq!(ok, vec!["C1", "C2"]); + assert_eq!(ok.unwrap(), vec!["C2", "C1"]); assert_eq!(err.len(), 0); let Outcome { completed: ok, errors: err, .. } = diff --git a/src/librustc_data_structures/sharded.rs b/src/librustc_data_structures/sharded.rs index 2f972eeccdcbd..31cb22098b8e9 100644 --- a/src/librustc_data_structures/sharded.rs +++ b/src/librustc_data_structures/sharded.rs @@ -2,7 +2,6 @@ use std::hash::{Hasher, Hash}; use std::mem; use std::borrow::Borrow; use std::collections::hash_map::RawEntryMut; -use smallvec::SmallVec; use crate::fx::{FxHasher, FxHashMap}; use crate::sync::{Lock, LockGuard}; @@ -19,7 +18,7 @@ const SHARD_BITS: usize = 5; #[cfg(not(parallel_compiler))] const SHARD_BITS: usize = 0; -pub const SHARDS: usize = 1 << SHARD_BITS; +const SHARDS: usize = 1 << SHARD_BITS; /// An array of cache-line aligned inner locked structures with convenience methods. #[derive(Clone)] @@ -30,36 +29,21 @@ pub struct Sharded { impl Default for Sharded { #[inline] fn default() -> Self { - Self::new(|| T::default()) - } -} - -impl Sharded { - #[inline] - pub fn new(mut value: impl FnMut() -> T) -> Self { - // Create a vector of the values we want - let mut values: SmallVec<[_; SHARDS]> = (0..SHARDS).map(|_| { - CacheAligned(Lock::new(value())) - }).collect(); - - // Create an unintialized array let mut shards: mem::MaybeUninit<[CacheAligned>; SHARDS]> = mem::MaybeUninit::uninit(); - + let first = shards.as_mut_ptr() as *mut CacheAligned>; unsafe { - // Copy the values into our array - let first = shards.as_mut_ptr() as *mut CacheAligned>; - values.as_ptr().copy_to_nonoverlapping(first, SHARDS); - - // Ignore the content of the vector - values.set_len(0); - + for i in 0..SHARDS { + first.add(i).write(CacheAligned(Lock::new(T::default()))); + } Sharded { shards: shards.assume_init(), } } } +} +impl Sharded { #[inline] pub fn get_shard_by_value(&self, val: &K) -> &Lock { if SHARDS == 1 { @@ -90,7 +74,7 @@ impl Sharded { pub type ShardedHashMap = Sharded>; -impl ShardedHashMap { +impl ShardedHashMap { pub fn len(&self) -> usize { self.lock_shards().iter().map(|shard| shard.len()).sum() } diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs index bdd3dc9665629..ce0aa07cc282c 100644 --- a/src/librustc_data_structures/snapshot_map/mod.rs +++ b/src/librustc_data_structures/snapshot_map/mod.rs @@ -7,7 +7,7 @@ use std::mem; mod tests; pub struct SnapshotMap - where K: Clone + Eq + where K: Hash + Clone + Eq { map: FxHashMap, undo_log: Vec>, diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 092208cfe1db7..47dfc1d1688d0 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -1,9 +1,10 @@ use std::hash::{Hash, Hasher, BuildHasher}; +use std::marker::PhantomData; use std::mem; use smallvec::SmallVec; use crate::sip128::SipHasher128; -use rustc_index::vec; -use rustc_index::bit_set; +use crate::indexed_vec; +use crate::bit_set; /// When hashing something that ends up affecting properties like symbol names, /// we want these symbol names to be calculated independently of other factors @@ -12,53 +13,55 @@ use rustc_index::bit_set; /// To that end we always convert integers to little-endian format before /// hashing and the architecture dependent `isize` and `usize` types are /// extended to 64 bits if needed. -pub struct StableHasher { +pub struct StableHasher { state: SipHasher128, + width: PhantomData, } -impl ::std::fmt::Debug for StableHasher { +impl ::std::fmt::Debug for StableHasher { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { write!(f, "{:?}", self.state) } } pub trait StableHasherResult: Sized { - fn finish(hasher: StableHasher) -> Self; + fn finish(hasher: StableHasher) -> Self; } -impl StableHasher { +impl StableHasher { pub fn new() -> Self { StableHasher { state: SipHasher128::new_with_keys(0, 0), + width: PhantomData, } } - pub fn finish(self) -> W { + pub fn finish(self) -> W { W::finish(self) } } impl StableHasherResult for u128 { - fn finish(hasher: StableHasher) -> Self { + fn finish(hasher: StableHasher) -> Self { let (_0, _1) = hasher.finalize(); u128::from(_0) | (u128::from(_1) << 64) } } impl StableHasherResult for u64 { - fn finish(hasher: StableHasher) -> Self { + fn finish(hasher: StableHasher) -> Self { hasher.finalize().0 } } -impl StableHasher { +impl StableHasher { #[inline] pub fn finalize(self) -> (u64, u64) { self.state.finish128() } } -impl Hasher for StableHasher { +impl Hasher for StableHasher { fn finish(&self) -> u64 { panic!("use StableHasher::finalize instead"); } @@ -162,14 +165,16 @@ impl Hasher for StableHasher { /// `StableHasher` takes care of endianness and `isize`/`usize` platform /// differences. pub trait HashStable { - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher); + fn hash_stable(&self, + hcx: &mut CTX, + hasher: &mut StableHasher); } /// Implement this for types that can be turned into stable keys like, for /// example, for DefId that can be converted to a DefPathHash. This is used for /// bringing maps into a predictable order before hashing them. pub trait ToStableHashKey { - type KeyType: Ord + Sized + HashStable; + type KeyType: Ord + Clone + Sized + HashStable; fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType; } @@ -180,10 +185,10 @@ macro_rules! impl_stable_hash_via_hash { ($t:ty) => ( impl $crate::stable_hasher::HashStable for $t { #[inline] - fn hash_stable( + fn hash_stable( &self, _: &mut CTX, - hasher: &mut $crate::stable_hasher::StableHasher + hasher: &mut $crate::stable_hasher::StableHasher ) { ::std::hash::Hash::hash(self, hasher); } @@ -210,13 +215,17 @@ impl_stable_hash_via_hash!(char); impl_stable_hash_via_hash!(()); impl HashStable for ::std::num::NonZeroU32 { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { self.get().hash_stable(ctx, hasher) } } impl HashStable for f32 { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { let val: u32 = unsafe { ::std::mem::transmute(*self) }; @@ -225,7 +234,9 @@ impl HashStable for f32 { } impl HashStable for f64 { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { let val: u64 = unsafe { ::std::mem::transmute(*self) }; @@ -234,20 +245,26 @@ impl HashStable for f64 { } impl HashStable for ::std::cmp::Ordering { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { (*self as i8).hash_stable(ctx, hasher); } } impl, CTX> HashStable for (T1,) { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { let (ref _0,) = *self; _0.hash_stable(ctx, hasher); } } impl, T2: HashStable, CTX> HashStable for (T1, T2) { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { let (ref _0, ref _1) = *self; _0.hash_stable(ctx, hasher); _1.hash_stable(ctx, hasher); @@ -259,7 +276,9 @@ impl HashStable for (T1, T2, T3) T2: HashStable, T3: HashStable, { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { let (ref _0, ref _1, ref _2) = *self; _0.hash_stable(ctx, hasher); _1.hash_stable(ctx, hasher); @@ -273,7 +292,9 @@ impl HashStable for (T1, T2, T3, T4) T3: HashStable, T4: HashStable, { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { let (ref _0, ref _1, ref _2, ref _3) = *self; _0.hash_stable(ctx, hasher); _1.hash_stable(ctx, hasher); @@ -283,7 +304,9 @@ impl HashStable for (T1, T2, T3, T4) } impl, CTX> HashStable for [T] { - default fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + default fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { self.len().hash_stable(ctx, hasher); for item in self { item.hash_stable(ctx, hasher); @@ -293,7 +316,9 @@ impl, CTX> HashStable for [T] { impl, CTX> HashStable for Vec { #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { (&self[..]).hash_stable(ctx, hasher); } } @@ -304,7 +329,9 @@ impl HashStable for indexmap::IndexMap R: BuildHasher, { #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { self.len().hash_stable(ctx, hasher); for kv in self { kv.hash_stable(ctx, hasher); @@ -317,7 +344,9 @@ impl HashStable for indexmap::IndexSet R: BuildHasher, { #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { self.len().hash_stable(ctx, hasher); for key in self { key.hash_stable(ctx, hasher); @@ -327,35 +356,45 @@ impl HashStable for indexmap::IndexSet impl HashStable for SmallVec<[A; 1]> where A: HashStable { #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { (&self[..]).hash_stable(ctx, hasher); } } impl, CTX> HashStable for Box { #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { (**self).hash_stable(ctx, hasher); } } impl, CTX> HashStable for ::std::rc::Rc { #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { (**self).hash_stable(ctx, hasher); } } impl, CTX> HashStable for ::std::sync::Arc { #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { (**self).hash_stable(ctx, hasher); } } impl HashStable for str { #[inline] - fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + _: &mut CTX, + hasher: &mut StableHasher) { self.len().hash(hasher); self.as_bytes().hash(hasher); } @@ -364,7 +403,9 @@ impl HashStable for str { impl HashStable for String { #[inline] - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut CTX, + hasher: &mut StableHasher) { (&self[..]).hash_stable(hcx, hasher); } } @@ -379,7 +420,9 @@ impl ToStableHashKey for String { impl HashStable for bool { #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { (if *self { 1u8 } else { 0u8 }).hash_stable(ctx, hasher); } } @@ -389,7 +432,9 @@ impl HashStable for Option where T: HashStable { #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { if let Some(ref value) = *self { 1u8.hash_stable(ctx, hasher); value.hash_stable(ctx, hasher); @@ -404,7 +449,9 @@ impl HashStable for Result T2: HashStable, { #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(ctx, hasher); match *self { Ok(ref x) => x.hash_stable(ctx, hasher), @@ -417,22 +464,28 @@ impl<'a, T, CTX> HashStable for &'a T where T: HashStable + ?Sized { #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { (**self).hash_stable(ctx, hasher); } } impl HashStable for ::std::mem::Discriminant { #[inline] - fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + _: &mut CTX, + hasher: &mut StableHasher) { ::std::hash::Hash::hash(self, hasher); } } -impl HashStable for vec::IndexVec +impl HashStable for indexed_vec::IndexVec where T: HashStable, { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { self.len().hash_stable(ctx, hasher); for v in &self.raw { v.hash_stable(ctx, hasher); @@ -441,17 +494,21 @@ impl HashStable for vec::IndexVec } -impl HashStable for bit_set::BitSet +impl HashStable for bit_set::BitSet { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { self.words().hash_stable(ctx, hasher); } } -impl HashStable +impl HashStable for bit_set::BitMatrix { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { self.words().hash_stable(ctx, hasher); } } @@ -460,21 +517,25 @@ impl_stable_hash_via_hash!(::std::path::Path); impl_stable_hash_via_hash!(::std::path::PathBuf); impl HashStable for ::std::collections::HashMap - where K: ToStableHashKey + Eq, + where K: ToStableHashKey + Eq + Hash, V: HashStable, R: BuildHasher, { #[inline] - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut HCX, + hasher: &mut StableHasher) { hash_stable_hashmap(hcx, hasher, self, ToStableHashKey::to_stable_hash_key); } } impl HashStable for ::std::collections::HashSet - where K: ToStableHashKey + Eq, + where K: ToStableHashKey + Eq + Hash, R: BuildHasher, { - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut HCX, + hasher: &mut StableHasher) { let mut keys: Vec<_> = self.iter() .map(|k| k.to_stable_hash_key(hcx)) .collect(); @@ -487,7 +548,9 @@ impl HashStable for ::std::collections::BTreeMap where K: ToStableHashKey, V: HashStable, { - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut HCX, + hasher: &mut StableHasher) { let mut entries: Vec<_> = self.iter() .map(|(k, v)| (k.to_stable_hash_key(hcx), v)) .collect(); @@ -499,7 +562,9 @@ impl HashStable for ::std::collections::BTreeMap impl HashStable for ::std::collections::BTreeSet where K: ToStableHashKey, { - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut HCX, + hasher: &mut StableHasher) { let mut keys: Vec<_> = self.iter() .map(|k| k.to_stable_hash_key(hcx)) .collect(); @@ -508,16 +573,17 @@ impl HashStable for ::std::collections::BTreeSet } } -pub fn hash_stable_hashmap( +pub fn hash_stable_hashmap( hcx: &mut HCX, - hasher: &mut StableHasher, + hasher: &mut StableHasher, map: &::std::collections::HashMap, to_stable_hash_key: F) - where K: Eq, + where K: Eq + Hash, V: HashStable, R: BuildHasher, - SK: HashStable + Ord, + SK: HashStable + Ord + Clone, F: Fn(&K, &HCX) -> SK, + W: StableHasherResult, { let mut entries: Vec<_> = map.iter() .map(|(k, v)| (to_stable_hash_key(k, hcx), v)) @@ -548,7 +614,9 @@ impl ::std::ops::Deref for StableVec { impl HashStable for StableVec where T: HashStable + ToStableHashKey { - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut HCX, + hasher: &mut StableHasher) { let StableVec(ref v) = *self; let mut sorted: Vec<_> = v.iter() diff --git a/src/librustc_data_structures/svh.rs b/src/librustc_data_structures/svh.rs index 64042264d794f..3123c182b0f4c 100644 --- a/src/librustc_data_structures/svh.rs +++ b/src/librustc_data_structures/svh.rs @@ -61,7 +61,11 @@ impl Decodable for Svh { impl stable_hasher::HashStable for Svh { #[inline] - fn hash_stable(&self, ctx: &mut T, hasher: &mut stable_hasher::StableHasher) { + fn hash_stable( + &self, + ctx: &mut T, + hasher: &mut stable_hasher::StableHasher + ) { let Svh { hash } = *self; diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index f09474ff4d344..3277b85c28144 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -1,6 +1,6 @@ //! This module defines types which are thread safe if cfg!(parallel_compiler) is true. //! -//! `Lrc` is an alias of `Arc` if cfg!(parallel_compiler) is true, `Rc` otherwise. +//! `Lrc` is an alias of either Rc or Arc. //! //! `Lock` is a mutex. //! It internally uses `parking_lot::Mutex` if cfg!(parallel_compiler) is true, @@ -12,7 +12,7 @@ //! //! `MTLock` is a mutex which disappears if cfg!(parallel_compiler) is false. //! -//! `MTRef` is an immutable reference if cfg!(parallel_compiler), and a mutable reference otherwise. +//! `MTRef` is a immutable reference if cfg!(parallel_compiler), and an mutable reference otherwise. //! //! `rustc_erase_owner!` erases a OwningRef owner into Erased or Erased + Send + Sync //! depending on the value of cfg!(parallel_compiler). @@ -23,6 +23,29 @@ use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use crate::owning_ref::{Erased, OwningRef}; +pub fn serial_join(oper_a: A, oper_b: B) -> (RA, RB) + where A: FnOnce() -> RA, + B: FnOnce() -> RB +{ + (oper_a(), oper_b()) +} + +pub struct SerialScope; + +impl SerialScope { + pub fn spawn(&self, f: F) + where F: FnOnce(&SerialScope) + { + f(self) + } +} + +pub fn serial_scope(f: F) -> R + where F: FnOnce(&SerialScope) -> R +{ + f(&SerialScope) +} + pub use std::sync::atomic::Ordering::SeqCst; pub use std::sync::atomic::Ordering; @@ -153,28 +176,8 @@ cfg_if! { pub type AtomicU32 = Atomic; pub type AtomicU64 = Atomic; - pub fn join(oper_a: A, oper_b: B) -> (RA, RB) - where A: FnOnce() -> RA, - B: FnOnce() -> RB - { - (oper_a(), oper_b()) - } - - pub struct SerialScope; - - impl SerialScope { - pub fn spawn(&self, f: F) - where F: FnOnce(&SerialScope) - { - f(self) - } - } - - pub fn scope(f: F) -> R - where F: FnOnce(&SerialScope) -> R - { - f(&SerialScope) - } + pub use self::serial_join as join; + pub use self::serial_scope as scope; #[macro_export] macro_rules! parallel { @@ -738,7 +741,7 @@ impl Clone for RwLock { /// A type which only allows its inner value to be used in one thread. /// It will panic if it is used on multiple threads. -#[derive(Debug)] +#[derive(Copy, Clone, Hash, Debug, Eq, PartialEq)] pub struct OneThread { #[cfg(parallel_compiler)] thread: thread::ThreadId, diff --git a/src/librustc_data_structures/thin_vec.rs b/src/librustc_data_structures/thin_vec.rs index d97da489db8df..6692903cd4fe9 100644 --- a/src/librustc_data_structures/thin_vec.rs +++ b/src/librustc_data_structures/thin_vec.rs @@ -1,9 +1,9 @@ -use crate::stable_hasher::{StableHasher, HashStable}; +use crate::stable_hasher::{StableHasher, StableHasherResult, HashStable}; /// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`). /// The `Option>` wrapping allows us to represent a zero sized vector with `None`, /// which uses only a single (null) pointer. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct ThinVec(Option>>); impl ThinVec { @@ -60,7 +60,9 @@ impl Extend for ThinVec { } impl, CTX> HashStable for ThinVec { - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut CTX, + hasher: &mut StableHasher) { (**self).hash_stable(hcx, hasher) } } diff --git a/src/librustc_data_structures/tiny_list.rs b/src/librustc_data_structures/tiny_list.rs index 371f0f6fa0b44..ea771d9f20f8b 100644 --- a/src/librustc_data_structures/tiny_list.rs +++ b/src/librustc_data_structures/tiny_list.rs @@ -14,7 +14,7 @@ #[cfg(test)] mod tests; -#[derive(Clone)] +#[derive(Clone, Hash, Debug, PartialEq)] pub struct TinyList { head: Option> } @@ -80,7 +80,7 @@ impl TinyList { } } -#[derive(Clone)] +#[derive(Clone, Hash, Debug, PartialEq)] struct Element { data: T, next: Option>>, diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs index a3926c1555172..ffc964ddb5ae2 100644 --- a/src/librustc_data_structures/transitive_relation.rs +++ b/src/librustc_data_structures/transitive_relation.rs @@ -1,6 +1,6 @@ -use rustc_index::bit_set::BitMatrix; +use crate::bit_set::BitMatrix; use crate::fx::FxHashMap; -use crate::stable_hasher::{HashStable, StableHasher}; +use crate::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use crate::sync::Lock; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; use std::fmt::Debug; @@ -11,7 +11,7 @@ use std::mem; mod tests; #[derive(Clone, Debug)] -pub struct TransitiveRelation { +pub struct TransitiveRelation { // List of elements. This is used to map from a T to a usize. elements: Vec, @@ -35,7 +35,7 @@ pub struct TransitiveRelation { } // HACK(eddyb) manual impl avoids `Default` bound on `T`. -impl Default for TransitiveRelation { +impl Default for TransitiveRelation { fn default() -> Self { TransitiveRelation { elements: Default::default(), @@ -46,7 +46,7 @@ impl Default for TransitiveRelation { } } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, RustcEncodable, RustcDecodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)] struct Index(usize); #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] @@ -442,7 +442,9 @@ impl Decodable for TransitiveRelation impl HashStable for TransitiveRelation where T: HashStable + Eq + Debug + Clone + Hash { - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut CTX, + hasher: &mut StableHasher) { // We are assuming here that the relation graph has been built in a // deterministic way and we can just hash it the way it is. let TransitiveRelation { @@ -460,7 +462,9 @@ impl HashStable for TransitiveRelation } impl HashStable for Edge { - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut CTX, + hasher: &mut StableHasher) { let Edge { ref source, ref target, @@ -472,7 +476,9 @@ impl HashStable for Edge { } impl HashStable for Index { - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut CTX, + hasher: &mut StableHasher) { let Index(idx) = *self; idx.hash_stable(hcx, hasher); } diff --git a/src/librustc_data_structures/vec_linked_list.rs b/src/librustc_data_structures/vec_linked_list.rs index 7744c30655dce..0fb8060031843 100644 --- a/src/librustc_data_structures/vec_linked_list.rs +++ b/src/librustc_data_structures/vec_linked_list.rs @@ -1,4 +1,4 @@ -use rustc_index::vec::{Idx, IndexVec}; +use crate::indexed_vec::{Idx, IndexVec}; pub fn iter( first: Option, diff --git a/src/librustc_data_structures/work_queue.rs b/src/librustc_data_structures/work_queue.rs index af63b18e9e922..193025aafad20 100644 --- a/src/librustc_data_structures/work_queue.rs +++ b/src/librustc_data_structures/work_queue.rs @@ -1,5 +1,5 @@ -use rustc_index::bit_set::BitSet; -use rustc_index::vec::Idx; +use crate::bit_set::BitSet; +use crate::indexed_vec::Idx; use std::collections::VecDeque; /// A work queue is a handy data structure for tracking work left to diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index a9e4e6db1c75f..aa74966d0ab4c 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -16,7 +16,6 @@ log = "0.4" env_logger = { version = "0.7", default-features = false } rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } -rustc_lint = { path = "../librustc_lint" } rustc_data_structures = { path = "../librustc_data_structures" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_metadata = { path = "../librustc_metadata" } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 15adf7e4add73..774a5af1b1ca8 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -36,11 +36,11 @@ use rustc::session::config::nightly_options; use rustc::session::{early_error, early_warn}; use rustc::lint::Lint; use rustc::lint; -use rustc::middle::cstore::MetadataLoader; use rustc::hir::def_id::LOCAL_CRATE; 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; use rustc_interface::interface; use rustc_interface::util::get_codegen_sysroot; @@ -106,8 +106,6 @@ pub fn abort_on_err(result: Result, sess: &Session) -> T { pub trait Callbacks { /// Called before creating the compiler instance fn config(&mut self, _config: &mut interface::Config) {} - /// Called early during compilation to allow other drivers to easily register lints. - fn extra_lints(&mut self, _ls: &mut lint::LintStore) {} /// Called after parsing. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) fn after_parsing(&mut self, _compiler: &interface::Compiler) -> Compilation { @@ -168,8 +166,7 @@ pub fn run_compiler( None => return Ok(()), }; - let sopts = config::build_session_options(&matches); - let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg")); + let (sopts, cfg) = config::build_session_options_and_crate_config(&matches); let mut dummy_config = |sopts, cfg, diagnostic_output| { let mut config = interface::Config { @@ -184,7 +181,6 @@ pub fn run_compiler( stderr: None, crate_name: None, lint_caps: Default::default(), - register_lints: None, }; callbacks.config(&mut config); config @@ -205,13 +201,9 @@ pub fn run_compiler( interface::run_compiler(config, |compiler| { let sopts = &compiler.session().opts; if sopts.describe_lints { - let lint_store = rustc_lint::new_lint_store( - sopts.debugging_opts.no_interleave_lints, - compiler.session().unstable_options(), - ); describe_lints( compiler.session(), - &lint_store, + &*compiler.session().lint_store.borrow(), false ); return; @@ -262,7 +254,6 @@ pub fn run_compiler( stderr: None, crate_name: None, lint_caps: Default::default(), - register_lints: None, }; callbacks.config(&mut config); @@ -277,7 +268,7 @@ pub fn run_compiler( compiler.output_file(), ).and_then(|| RustcDefaultCalls::list_metadata( sess, - &*compiler.codegen_backend().metadata_loader(), + compiler.cstore(), &matches, compiler.input() )); @@ -329,14 +320,12 @@ pub fn run_compiler( return sess.compile_status(); } - { - let (_, _, lint_store) = &*compiler.register_plugins()?.peek(); + compiler.register_plugins()?; - // Lint plugins are registered; now we can process command line flags. - if sess.opts.describe_lints { - describe_lints(&sess, &lint_store, true); - return sess.compile_status(); - } + // Lint plugins are registered; now we can process command line flags. + if sess.opts.describe_lints { + describe_lints(&sess, &sess.lint_store.borrow(), true); + return sess.compile_status(); } compiler.expansion()?; @@ -614,7 +603,7 @@ fn show_content_with_pager(content: &String) { impl RustcDefaultCalls { pub fn list_metadata(sess: &Session, - metadata_loader: &dyn MetadataLoader, + cstore: &CStore, matches: &getopts::Matches, input: &Input) -> Compilation { @@ -626,7 +615,7 @@ impl RustcDefaultCalls { let mut v = Vec::new(); locator::list_file_metadata(&sess.target.target, path, - metadata_loader, + &*cstore.metadata_loader, &mut v) .unwrap(); println!("{}", String::from_utf8(v).unwrap()); @@ -845,7 +834,8 @@ Available lint options: "); - fn sort_lints(sess: &Session, mut lints: Vec<&'static Lint>) -> Vec<&'static Lint> { + fn sort_lints(sess: &Session, lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> { + let mut lints: Vec<_> = lints.into_iter().map(|(x, _)| x).collect(); // The sort doesn't case-fold but it's doubtful we care. lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess), x.name)); lints @@ -861,7 +851,7 @@ Available lint options: let (plugin, builtin): (Vec<_>, _) = lint_store.get_lints() .iter() .cloned() - .partition(|&lint| lint.is_plugin); + .partition(|&(_, p)| p); let plugin = sort_lints(sess, plugin); let builtin = sort_lints(sess, builtin); @@ -1241,7 +1231,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false); if backtrace { - TyCtxt::try_print_query_stack(&handler); + TyCtxt::try_print_query_stack(); } #[cfg(windows)] diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index 491bc2aa6a2eb..0281d10fd930e 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -31,28 +31,24 @@ pub struct AnnotateSnippetEmitterWriter { impl Emitter for AnnotateSnippetEmitterWriter { /// The entry point for the diagnostics generation - fn emit_diagnostic(&mut self, diag: &Diagnostic) { - let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(&diag); + 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.source_map, &mut primary_span, &mut children, - &diag.level, + &db.level, self.external_macro_backtrace); - self.emit_messages_default(&diag.level, - diag.message(), - &diag.code, + self.emit_messages_default(&db.level, + db.message(), + &db.code, &primary_span, &children, &suggestions); } - fn source_map(&self) -> Option<&Lrc> { - self.source_map.as_ref() - } - fn should_show_explain(&self) -> bool { !self.short_message } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 1781f2e165033..3f1b91256c468 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -152,32 +152,6 @@ impl Diagnostic { self.note_expected_found_extra(label, expected, found, &"", &"") } - pub fn note_unsuccessfull_coercion(&mut self, - expected: DiagnosticStyledString, - found: DiagnosticStyledString) - -> &mut Self - { - let mut msg: Vec<_> = - vec![(format!("required when trying to coerce from type `"), - Style::NoStyle)]; - msg.extend(expected.0.iter() - .map(|x| match *x { - StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), - StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), - })); - msg.push((format!("` to type '"), Style::NoStyle)); - msg.extend(found.0.iter() - .map(|x| match *x { - StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), - StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), - })); - msg.push((format!("`"), Style::NoStyle)); - - // For now, just attach these as notes - self.highlighted_note(msg); - self - } - pub fn note_expected_found_extra(&mut self, label: &dyn fmt::Display, expected: DiagnosticStyledString, @@ -324,31 +298,9 @@ impl Diagnostic { /// * may contain a name of a function, variable, or type, but not whole expressions /// /// See `CodeSuggestion` for more information. - pub fn span_suggestion( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - ) -> &mut Self { - self.span_suggestion_with_style( - sp, - msg, - suggestion, - applicability, - SuggestionStyle::ShowCode, - ); - self - } - - pub fn span_suggestion_with_style( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - style: SuggestionStyle, - ) -> &mut Self { + pub fn span_suggestion(&mut self, sp: Span, msg: &str, + suggestion: String, + applicability: Applicability) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: vec![Substitution { parts: vec![SubstitutionPart { @@ -357,37 +309,16 @@ impl Diagnostic { }], }], msg: msg.to_owned(), - style, + style: SuggestionStyle::ShowCode, applicability, }); self } - pub fn span_suggestion_verbose( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - ) -> &mut Self { - self.span_suggestion_with_style( - sp, - msg, - suggestion, - applicability, - SuggestionStyle::ShowAlways, - ); - self - } - /// Prints out a message with multiple suggested edits of the code. - pub fn span_suggestions( - &mut self, - sp: Span, - msg: &str, - suggestions: impl Iterator, - applicability: Applicability, - ) -> &mut Self { + pub fn span_suggestions(&mut self, sp: Span, msg: &str, + suggestions: impl Iterator, applicability: Applicability) -> &mut Self + { self.suggestions.push(CodeSuggestion { substitutions: suggestions.map(|snippet| Substitution { parts: vec![SubstitutionPart { @@ -409,13 +340,17 @@ impl Diagnostic { pub fn span_suggestion_short( &mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability ) -> &mut Self { - self.span_suggestion_with_style( - sp, - msg, - suggestion, + self.suggestions.push(CodeSuggestion { + substitutions: vec![Substitution { + parts: vec![SubstitutionPart { + snippet: suggestion, + span: sp, + }], + }], + msg: msg.to_owned(), + style: SuggestionStyle::HideCodeInline, applicability, - SuggestionStyle::HideCodeInline, - ); + }); self } @@ -428,13 +363,17 @@ impl Diagnostic { pub fn span_suggestion_hidden( &mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability ) -> &mut Self { - self.span_suggestion_with_style( - sp, - msg, - suggestion, + self.suggestions.push(CodeSuggestion { + substitutions: vec![Substitution { + parts: vec![SubstitutionPart { + snippet: suggestion, + span: sp, + }], + }], + msg: msg.to_owned(), + style: SuggestionStyle::HideCodeAlways, applicability, - SuggestionStyle::HideCodeAlways, - ); + }); self } @@ -445,13 +384,17 @@ impl Diagnostic { pub fn tool_only_span_suggestion( &mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability ) -> &mut Self { - self.span_suggestion_with_style( - sp, - msg, - suggestion, + self.suggestions.push(CodeSuggestion { + substitutions: vec![Substitution { + parts: vec![SubstitutionPart { + snippet: suggestion, + span: sp, + }], + }], + msg: msg.to_owned(), + style: SuggestionStyle::CompletelyHidden, applicability, - SuggestionStyle::CompletelyHidden, - ); + }); self } diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 40642dd14b8f7..cc60bf89c7eca 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -209,11 +209,6 @@ impl<'a> DiagnosticBuilder<'a> { found_extra: &dyn fmt::Display, ) -> &mut Self); - forward!(pub fn note_unsuccessfull_coercion(&mut self, - expected: DiagnosticStyledString, - found: DiagnosticStyledString, - ) -> &mut Self); - forward!(pub fn note(&mut self, msg: &str) -> &mut Self); forward!(pub fn span_note>(&mut self, sp: S, diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index e3b55a141338a..2a89c94652a24 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -12,8 +12,8 @@ use Destination::*; use syntax_pos::{SourceFile, Span, MultiSpan}; use crate::{ - Level, CodeSuggestion, Diagnostic, SubDiagnostic, pluralise, - SuggestionStyle, SourceMapper, SourceMapperDyn, DiagnosticId, + Level, CodeSuggestion, Diagnostic, SubDiagnostic, + SuggestionStyle, SourceMapperDyn, DiagnosticId, }; use crate::Level::Error; use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style}; @@ -99,8 +99,8 @@ impl Margin { // ``` let mut m = Margin { - whitespace_left: whitespace_left.saturating_sub(6), - span_left: span_left.saturating_sub(6), + 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, @@ -125,7 +125,7 @@ impl Margin { } else { self.computed_right }; - right < line_len && self.computed_left + self.column_width < line_len + right < line_len && line_len > self.computed_left + self.column_width } fn compute(&mut self, max_line_len: usize) { @@ -167,10 +167,12 @@ impl Margin { } fn right(&self, line_len: usize) -> usize { - if line_len.saturating_sub(self.computed_left) <= self.column_width { + 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 { - min(line_len, self.computed_right) + self.computed_right } } } @@ -180,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, diag: &Diagnostic); + 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, @@ -192,8 +194,6 @@ pub trait Emitter { true } - fn source_map(&self) -> Option<&Lrc>; - /// Formats the substitutions of the primary_span /// /// The are a lot of conditions to this method, but in short: @@ -206,10 +206,10 @@ pub trait Emitter { /// we return the original `primary_span` and the original suggestions. fn primary_span_formatted<'a>( &mut self, - diag: &'a Diagnostic, + db: &'a Diagnostic ) -> (MultiSpan, &'a [CodeSuggestion]) { - let mut primary_span = diag.span.clone(); - if let Some((sugg, rest)) = diag.suggestions.split_first() { + let mut primary_span = db.span.clone(); + 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 @@ -220,14 +220,10 @@ pub trait Emitter { sugg.msg.split_whitespace().count() < 10 && // don't display multiline suggestions as labels !sugg.substitutions[0].parts[0].snippet.contains('\n') && - ![ - // when this style is set we want the suggestion to be a message, not inline - SuggestionStyle::HideCodeAlways, - // trivial suggestion for tooling's sake, never shown - SuggestionStyle::CompletelyHidden, - // subtle suggestion, never shown inline - SuggestionStyle::ShowAlways, - ].contains(&sugg.style) + // when this style is set we want the suggestion to be a message, not inline + sugg.style != SuggestionStyle::HideCodeAlways && + // trivial suggestion for tooling's sake, never shown + sugg.style != SuggestionStyle::CompletelyHidden { let substitution = &sugg.substitutions[0].parts[0].snippet.trim(); let msg = if substitution.len() == 0 || sugg.style.hide_inline() { @@ -236,20 +232,7 @@ pub trait Emitter { format!("help: {}", sugg.msg) } else { // Show the default suggestion text with the substitution - format!( - "help: {}{}: `{}`", - sugg.msg, - if self.source_map().map(|sm| is_case_difference( - &**sm, - substitution, - sugg.substitutions[0].parts[0].span, - )).unwrap_or(false) { - " (notice the capitalization)" - } else { - "" - }, - substitution, - ) + format!("help: {}: `{}`", sugg.msg, substitution) }; primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg); @@ -260,10 +243,10 @@ pub trait Emitter { // 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 - (primary_span, &diag.suggestions) + (primary_span, &db.suggestions) } } else { - (primary_span, &diag.suggestions) + (primary_span, &db.suggestions) } } @@ -314,82 +297,81 @@ pub trait Emitter { source_map: &Option>, span: &mut MultiSpan, always_backtrace: bool) -> bool { - let sm = match source_map { - Some(ref sm) => sm, - None => return false, - }; + let mut spans_updated = false; - let mut before_after: Vec<(Span, Span)> = vec![]; - let mut new_labels: Vec<(Span, String)> = vec![]; + 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() { + // 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; } - 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() - }))); + let call_sp = sm.call_span_if_macro(*sp); + if call_sp != *sp && !always_backtrace { + before_after.push((*sp, call_sp)); } - // 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; + 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; + for (label_span, label_text) in new_labels { + span.push_span_label(label_span, label_text); } - 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())); + 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 - let spans_updated = !before_after.is_empty(); - for (before, after) in before_after { - span.replace(before, after); + // 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 @@ -397,23 +379,19 @@ pub trait Emitter { } impl Emitter for EmitterWriter { - fn source_map(&self) -> Option<&Lrc> { - self.sm.as_ref() - } - - fn emit_diagnostic(&mut self, diag: &Diagnostic) { - let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(&diag); + 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, - &diag.level, + &db.level, self.external_macro_backtrace); - self.emit_messages_default(&diag.level, - &diag.styled_message(), - &diag.code, + self.emit_messages_default(&db.level, + &db.styled_message(), + &db.code, &primary_span, &children, &suggestions); @@ -615,9 +593,9 @@ impl EmitterWriter { 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) - .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)) - .sum(); + let left = source_string.chars().take(left).fold(0, |acc, ch| { + acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) + }); self.draw_line( buffer, @@ -645,16 +623,18 @@ impl EmitterWriter { // 3 | | // 4 | | } // | |_^ test - if let [ann] = &line.annotations[..] { - if let AnnotationType::MultilineStart(depth) = ann.annotation_type { - 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); - return vec![(depth, style)]; + 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()) { + let style = if ann.is_primary { + Style::UnderlinePrimary + } else { + Style::UnderlineSecondary + }; + buffer.putc(line_offset, width_offset + depth - 1, '/', style); + return vec![(depth, style)]; + } } } } @@ -783,7 +763,11 @@ impl EmitterWriter { annotations_position.push((p, annotation)); for (j, next) in annotations.iter().enumerate() { if j > i { - let l = next.label.as_ref().map_or(0, |label| label.len() + 2); + let l = if let Some(ref label) = next.label { + label.len() + 2 + } else { + 0 + }; if (overlaps(next, annotation, l) // Do not allow two labels to be in the same // line if they overlap including padding, to // avoid situations like: @@ -813,7 +797,9 @@ impl EmitterWriter { } } } - line_len = max(line_len, p); + if line_len < p { + line_len = p; + } } if line_len != 0 { @@ -955,9 +941,17 @@ impl EmitterWriter { Style::LabelSecondary }; let (pos, col) = if pos == 0 { - (pos + 1, (annotation.end_col + 1).saturating_sub(left)) + (pos + 1, if annotation.end_col + 1 > left { + annotation.end_col + 1 - left + } else { + 0 + }) } else { - (pos + 2, annotation.start_col.saturating_sub(left)) + (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); @@ -972,9 +966,9 @@ impl EmitterWriter { // | | | // | | something about `foo` // | something about `fn foo()` - annotations_position.sort_by_key(|(_, ann)| { - // Decreasing order. When annotations share the same length, prefer `Primary`. - (Reverse(ann.len()), ann.is_primary) + annotations_position.sort_by(|a, b| { + // Decreasing order. When `a` and `b` are the same length, prefer `Primary`. + (a.1.len(), !a.1.is_primary).cmp(&(b.1.len(), !b.1.is_primary)).reverse() }); // Write the underlines. @@ -997,7 +991,11 @@ impl EmitterWriter { for p in annotation.start_col..annotation.end_col { buffer.putc( line_offset + 1, - (code_offset + p).saturating_sub(left), + if code_offset + p > left { + code_offset + p - left + } else { + 0 + }, underline, style, ); @@ -1020,37 +1018,40 @@ impl EmitterWriter { } fn get_multispan_max_line_num(&mut self, msp: &MultiSpan) -> usize { - let sm = match self.sm { - Some(ref sm) => sm, - None => return 0, - }; - let mut max = 0; - for primary_span in msp.primary_spans() { - if !primary_span.is_dummy() { - let hi = sm.lookup_char_pos(primary_span.hi()); - max = (hi.line).max(max); + if let Some(ref sm) = self.sm { + for primary_span in msp.primary_spans() { + if !primary_span.is_dummy() { + let hi = sm.lookup_char_pos(primary_span.hi()); + if hi.line > max { + max = hi.line; + } + } } - } - if !self.short_message { - for span_label in msp.span_labels() { - if !span_label.span.is_dummy() { - let hi = sm.lookup_char_pos(span_label.span.hi()); - max = (hi.line).max(max); + if !self.short_message { + for span_label in msp.span_labels() { + if !span_label.span.is_dummy() { + let hi = sm.lookup_char_pos(span_label.span.hi()); + if hi.line > max { + max = hi.line; + } + } } } } - max } fn get_max_line_num(&mut self, span: &MultiSpan, children: &[SubDiagnostic]) -> usize { + let primary = self.get_multispan_max_line_num(span); - children.iter() - .map(|sub| self.get_multispan_max_line_num(&sub.span)) - .max() - .unwrap_or(0) - .max(primary) + let mut max = primary; + + for sub in children { + let sub_result = self.get_multispan_max_line_num(&sub.span); + max = std::cmp::max(sub_result, max); + } + max } /// Adds a left margin to every line but the first, given a padding length and the label being @@ -1080,12 +1081,14 @@ impl EmitterWriter { // `max_line_num_len` let padding = " ".repeat(padding + label.len() + 5); - /// Returns `override` if it is present and `style` is `NoStyle` or `style` otherwise - fn style_or_override(style: Style, override_: Option\n\n").unwrap(); + trace::write_traces(&mut html_file, &mut counts_file, &frame.traces); + writeln!(html_file, "\n").unwrap(); + + let ack_path = format!("{}.ack", params.path); + let ack_file = File::create(&ack_path).unwrap(); + drop(ack_file); + + // Tell main thread that we are done, e.g., so it can exit + params.ack.send(()).unwrap(); + } + // Actual query message: + msg => { + // Record msg in our log + profq_msgs.push(msg.clone()); + // Respond to the message, knowing that we've already handled Halt and Dump, above. + match (frame.parse_st.clone(), msg) { + (_, ProfileQueriesMsg::Halt) | (_, ProfileQueriesMsg::Dump(_)) => { + unreachable!(); + }, + // Parse State: Clear + (ParseState::Clear, + ProfileQueriesMsg::QueryBegin(span, querymsg)) => { + let start = Instant::now(); + frame.parse_st = ParseState::HaveQuery + (Query { span, msg: querymsg }, start) + }, + (ParseState::Clear, + ProfileQueriesMsg::CacheHit) => { + panic!("parse error: unexpected CacheHit; expected QueryBegin") + }, + (ParseState::Clear, + ProfileQueriesMsg::ProviderBegin) => { + panic!("parse error: expected QueryBegin before beginning a provider") + }, + (ParseState::Clear, + ProfileQueriesMsg::ProviderEnd) => { + let provider_extent = frame.traces; + match stack.pop() { + None => + panic!("parse error: expected a stack frame; found an empty stack"), + Some(old_frame) => { + match old_frame.parse_st { + ParseState::HaveQuery(q, start) => { + let duration = start.elapsed(); + frame = StackFrame{ + parse_st: ParseState::Clear, + traces: old_frame.traces + }; + let dur_extent = total_duration(&provider_extent); + let trace = Rec { + effect: Effect::QueryBegin(q, CacheCase::Miss), + extent: Box::new(provider_extent), + start: start, + dur_self: duration - dur_extent, + dur_total: duration, + }; + frame.traces.push( trace ); + }, + _ => panic!("internal parse error: malformed parse stack") + } + } + } + }, + (ParseState::Clear, + ProfileQueriesMsg::TimeBegin(msg)) => { + let start = Instant::now(); + frame.parse_st = ParseState::HaveTimeBegin(msg, start); + stack.push(frame); + frame = StackFrame{parse_st: ParseState::Clear, traces: vec![]}; + }, + (_, ProfileQueriesMsg::TimeBegin(_)) => { + panic!("parse error; did not expect time begin here"); + }, + (ParseState::Clear, + ProfileQueriesMsg::TimeEnd) => { + let provider_extent = frame.traces; + match stack.pop() { + None => + panic!("parse error: expected a stack frame; found an empty stack"), + Some(old_frame) => { + match old_frame.parse_st { + ParseState::HaveTimeBegin(msg, start) => { + let duration = start.elapsed(); + frame = StackFrame{ + parse_st: ParseState::Clear, + traces: old_frame.traces + }; + let dur_extent = total_duration(&provider_extent); + let trace = Rec { + effect: Effect::TimeBegin(msg), + extent: Box::new(provider_extent), + start: start, + dur_total: duration, + dur_self: duration - dur_extent, + }; + frame.traces.push( trace ); + }, + _ => panic!("internal parse error: malformed parse stack") + } + } + } + }, + (_, ProfileQueriesMsg::TimeEnd) => { + panic!("parse error") + }, + (ParseState::Clear, + ProfileQueriesMsg::TaskBegin(key)) => { + let start = Instant::now(); + frame.parse_st = ParseState::HaveTaskBegin(key, start); + stack.push(frame); + frame = StackFrame{ parse_st: ParseState::Clear, traces: vec![] }; + }, + (_, ProfileQueriesMsg::TaskBegin(_)) => { + panic!("parse error; did not expect time begin here"); + }, + (ParseState::Clear, + ProfileQueriesMsg::TaskEnd) => { + let provider_extent = frame.traces; + match stack.pop() { + None => + panic!("parse error: expected a stack frame; found an empty stack"), + Some(old_frame) => { + match old_frame.parse_st { + ParseState::HaveTaskBegin(key, start) => { + let duration = start.elapsed(); + frame = StackFrame{ + parse_st: ParseState::Clear, + traces: old_frame.traces + }; + let dur_extent = total_duration(&provider_extent); + let trace = Rec { + effect: Effect::TaskBegin(key), + extent: Box::new(provider_extent), + start: start, + dur_total: duration, + dur_self: duration - dur_extent, + }; + frame.traces.push( trace ); + }, + _ => panic!("internal parse error: malformed parse stack") + } + } + } + }, + (_, ProfileQueriesMsg::TaskEnd) => { + panic!("parse error") + }, + // Parse State: HaveQuery + (ParseState::HaveQuery(q,start), + ProfileQueriesMsg::CacheHit) => { + let duration = start.elapsed(); + let trace : Rec = Rec{ + effect: Effect::QueryBegin(q, CacheCase::Hit), + extent: Box::new(vec![]), + start: start, + dur_self: duration, + dur_total: duration, + }; + frame.traces.push( trace ); + frame.parse_st = ParseState::Clear; + }, + (ParseState::HaveQuery(_, _), + ProfileQueriesMsg::ProviderBegin) => { + stack.push(frame); + frame = StackFrame{ parse_st: ParseState::Clear, traces: vec![] }; + }, + + // Parse errors: + + (ParseState::HaveQuery(q, _), + ProfileQueriesMsg::ProviderEnd) => { + panic!("parse error: unexpected ProviderEnd; \ + expected something else to follow BeginQuery for {:?}", q) + }, + (ParseState::HaveQuery(q1, _), + ProfileQueriesMsg::QueryBegin(span2, querymsg2)) => { + panic!("parse error: unexpected QueryBegin; \ + earlier query is unfinished: {:?} and now {:?}", + q1, Query{span:span2, msg: querymsg2}) + }, + (ParseState::HaveTimeBegin(_, _), _) => { + unreachable!() + }, + (ParseState::HaveTaskBegin(_, _), _) => { + unreachable!() + }, + } + } + } + } +} diff --git a/src/librustc_interface/profile/trace.rs b/src/librustc_interface/profile/trace.rs new file mode 100644 index 0000000000000..95c4ea6ff2347 --- /dev/null +++ b/src/librustc_interface/profile/trace.rs @@ -0,0 +1,304 @@ +use super::*; +use syntax_pos::SpanData; +use rustc_data_structures::fx::FxHashMap; +use rustc::util::common::QueryMsg; +use std::fs::File; +use std::time::{Duration, Instant}; +use rustc::dep_graph::{DepNode}; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct Query { + pub span: SpanData, + pub msg: QueryMsg, +} +pub enum Effect { + QueryBegin(Query, CacheCase), + TimeBegin(String), + TaskBegin(DepNode), +} +pub enum CacheCase { + Hit, Miss +} +/// Recursive trace structure +pub struct Rec { + pub effect: Effect, + pub start: Instant, + pub dur_self: Duration, + pub dur_total: Duration, + pub extent: Box>, +} +pub struct QueryMetric { + pub count: usize, + pub dur_self: Duration, + pub dur_total: Duration, +} + +fn cons(s: &str) -> String { + let first = s.split(|d| d == '(' || d == '{').next(); + assert!(first.is_some() && first != Some("")); + first.unwrap().to_owned() +} + +pub fn cons_of_query_msg(q: &trace::Query) -> String { + cons(&format!("{:?}", q.msg)) +} + +pub fn cons_of_key(k: &DepNode) -> String { + cons(&format!("{:?}", k)) +} + +// First return value is text; second return value is a CSS class +pub fn html_of_effect(eff: &Effect) -> (String, String) { + match *eff { + Effect::TimeBegin(ref msg) => { + (msg.clone(), + "time-begin".to_string()) + }, + Effect::TaskBegin(ref key) => { + let cons = cons_of_key(key); + (cons.clone(), format!("{} task-begin", cons)) + }, + Effect::QueryBegin(ref qmsg, ref cc) => { + let cons = cons_of_query_msg(qmsg); + (cons.clone(), + format!("{} {}", + cons, + match *cc { + CacheCase::Hit => "hit", + CacheCase::Miss => "miss", + })) + } + } +} + +// First return value is text; second return value is a CSS class +fn html_of_duration(_start: &Instant, dur: &Duration) -> (String, String) { + use rustc::util::common::duration_to_secs_str; + (duration_to_secs_str(dur.clone()), String::new()) +} + +fn html_of_fraction(frac: f64) -> (String, &'static str) { + let css = { + if frac > 0.50 { "frac-50" } + else if frac > 0.40 { "frac-40" } + else if frac > 0.30 { "frac-30" } + else if frac > 0.20 { "frac-20" } + else if frac > 0.10 { "frac-10" } + else if frac > 0.05 { "frac-05" } + else if frac > 0.02 { "frac-02" } + else if frac > 0.01 { "frac-01" } + else if frac > 0.001 { "frac-001" } + else { "frac-0" } + }; + let percent = frac * 100.0; + + if percent > 0.1 { + (format!("{:.1}%", percent), css) + } else { + ("< 0.1%".to_string(), css) + } +} + +fn total_duration(traces: &[Rec]) -> Duration { + Duration::new(0, 0) + traces.iter().map(|t| t.dur_total).sum() +} + +fn duration_div(nom: Duration, den: Duration) -> f64 { + fn to_nanos(d: Duration) -> u64 { + d.as_secs() * 1_000_000_000 + d.subsec_nanos() as u64 + } + + to_nanos(nom) as f64 / to_nanos(den) as f64 +} + +fn write_traces_rec(file: &mut File, traces: &[Rec], total: Duration, depth: usize) { + for t in traces { + let (eff_text, eff_css_classes) = html_of_effect(&t.effect); + let (dur_text, dur_css_classes) = html_of_duration(&t.start, &t.dur_total); + let fraction = duration_div(t.dur_total, total); + let percent = fraction * 100.0; + let (frc_text, frc_css_classes) = html_of_fraction(fraction); + writeln!(file, "

").unwrap(); + } +} + +fn compute_counts_rec(counts: &mut FxHashMap, traces: &[Rec]) { + counts.reserve(traces.len()); + for t in traces.iter() { + match t.effect { + Effect::TimeBegin(ref msg) => { + let qm = match counts.get(msg) { + Some(_qm) => panic!("TimeBegin with non-unique, repeat message"), + None => QueryMetric { + count: 1, + dur_self: t.dur_self, + dur_total: t.dur_total, + } + }; + counts.insert(msg.clone(), qm); + }, + Effect::TaskBegin(ref key) => { + let cons = cons_of_key(key); + let qm = match counts.get(&cons) { + Some(qm) => + QueryMetric { + count: qm.count + 1, + dur_self: qm.dur_self + t.dur_self, + dur_total: qm.dur_total + t.dur_total, + }, + None => QueryMetric { + count: 1, + dur_self: t.dur_self, + dur_total: t.dur_total, + } + }; + counts.insert(cons, qm); + }, + Effect::QueryBegin(ref qmsg, ref _cc) => { + let qcons = cons_of_query_msg(qmsg); + let qm = match counts.get(&qcons) { + Some(qm) => + QueryMetric { + count: qm.count + 1, + dur_total: qm.dur_total + t.dur_total, + dur_self: qm.dur_self + t.dur_self + }, + None => QueryMetric { + count: 1, + dur_total: t.dur_total, + dur_self: t.dur_self, + } + }; + counts.insert(qcons, qm); + } + } + compute_counts_rec(counts, &t.extent) + } +} + +pub fn write_counts(count_file: &mut File, counts: &mut FxHashMap) { + use rustc::util::common::duration_to_secs_str; + use std::cmp::Reverse; + + let mut data = counts.iter().map(|(ref cons, ref qm)| + (cons.clone(), qm.count.clone(), qm.dur_total.clone(), qm.dur_self.clone()) + ).collect::>(); + + data.sort_by_key(|k| Reverse(k.3)); + for (cons, count, dur_total, dur_self) in data { + writeln!(count_file, "{}, {}, {}, {}", + cons, count, + duration_to_secs_str(dur_total), + duration_to_secs_str(dur_self) + ).unwrap(); + } +} + +pub fn write_traces(html_file: &mut File, counts_file: &mut File, traces: &[Rec]) { + let capacity = traces.iter().fold(0, |acc, t| acc + 1 + t.extent.len()); + let mut counts = FxHashMap::with_capacity_and_hasher(capacity, Default::default()); + compute_counts_rec(&mut counts, traces); + write_counts(counts_file, &mut counts); + + let total: Duration = total_duration(traces); + write_traces_rec(html_file, traces, total, 0) +} + +pub fn write_style(html_file: &mut File) { + write!(html_file, "{}", " +body { + font-family: sans-serif; + background: black; +} +.trace { + color: black; + display: inline-block; + border-style: solid; + border-color: red; + border-width: 1px; + border-radius: 5px; + padding: 0px; + margin: 1px; + font-size: 0px; +} +.task-begin { + border-width: 1px; + color: white; + border-color: #ff8; + font-size: 0px; +} +.miss { + border-color: red; + border-width: 1px; +} +.extent-0 { + padding: 2px; +} +.time-begin { + border-width: 4px; + font-size: 12px; + color: white; + border-color: #afa; +} +.important { + border-width: 3px; + font-size: 12px; + color: white; + border-color: #f77; +} +.hit { + padding: 0px; + border-color: blue; + border-width: 3px; +} +.eff { + color: #fff; + display: inline-block; +} +.frc { + color: #7f7; + display: inline-block; +} +.dur { + display: none +} +.frac-50 { + padding: 10px; + border-width: 10px; + font-size: 32px; +} +.frac-40 { + padding: 8px; + border-width: 8px; + font-size: 24px; +} +.frac-30 { + padding: 6px; + border-width: 6px; + font-size: 18px; +} +.frac-20 { + padding: 4px; + border-width: 6px; + font-size: 16px; +} +.frac-10 { + padding: 2px; + border-width: 6px; + font-size: 14px; +} +").unwrap(); +} diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index ea51e63725ea2..cd72dc9453c7e 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -1,17 +1,12 @@ use crate::interface::{Compiler, Result}; -use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt, PluginInfo}; +use crate::passes::{self, BoxedResolver, ExpansionResult, BoxedGlobalCtxt, PluginInfo}; use rustc_incremental::DepGraphFuture; -use rustc_data_structures::sync::Lrc; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::util::common::{time, ErrorReported}; use rustc::hir; -use rustc::lint; -use rustc::session::Session; -use rustc::lint::LintStore; use rustc::hir::def_id::LOCAL_CRATE; use rustc::ty::steal::Steal; -use rustc::ty::ResolverOutputs; use rustc::dep_graph::DepGraph; use std::cell::{Ref, RefMut, RefCell}; use std::rc::Rc; @@ -79,10 +74,10 @@ pub(crate) struct Queries { dep_graph_future: Query>, parse: Query, crate_name: Query, - register_plugins: Query<(ast::Crate, PluginInfo, Lrc)>, - expansion: Query<(ast::Crate, Steal>>, Lrc)>, + register_plugins: Query<(ast::Crate, PluginInfo)>, + expansion: Query<(ast::Crate, Steal>>)>, dep_graph: Query, - lower_to_hir: Query<(Steal, Steal)>, + lower_to_hir: Query<(Steal, ExpansionResult)>, prepare_outputs: Query, global_ctxt: Query, ongoing_codegen: Query>, @@ -111,19 +106,14 @@ impl Compiler { }) } - pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, PluginInfo, Lrc)>> { + pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, PluginInfo)>> { self.queries.register_plugins.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let krate = self.parse()?.take(); - let empty: &(dyn Fn(&Session, &mut lint::LintStore) + Sync + Send) = &|_, _| {}; let result = passes::register_plugins( self.session(), - &*self.codegen_backend().metadata_loader(), - self.register_lints - .as_ref() - .map(|p| &**p) - .unwrap_or_else(|| empty), + self.cstore(), krate, &crate_name, ); @@ -158,20 +148,17 @@ impl Compiler { pub fn expansion( &self - ) -> Result<&Query<(ast::Crate, Steal>>, Lrc)>> { + ) -> Result<&Query<(ast::Crate, Steal>>)>> { self.queries.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); - let (krate, plugin_info, lint_store) = self.register_plugins()?.take(); + let (krate, plugin_info) = self.register_plugins()?.take(); passes::configure_and_expand( self.sess.clone(), - lint_store.clone(), - self.codegen_backend().metadata_loader(), + self.cstore().clone(), krate, &crate_name, plugin_info, - ).map(|(krate, resolver)| { - (krate, Steal::new(Rc::new(RefCell::new(resolver))), lint_store) - }) + ).map(|(krate, resolver)| (krate, Steal::new(Rc::new(RefCell::new(resolver))))) }) } @@ -192,35 +179,32 @@ impl Compiler { }) } - pub fn lower_to_hir( - &self, - ) -> Result<&Query<(Steal, Steal)>> { + pub fn lower_to_hir(&self) -> Result<&Query<(Steal, ExpansionResult)>> { self.queries.lower_to_hir.compute(|| { let expansion_result = self.expansion()?; let peeked = expansion_result.peek(); let krate = &peeked.0; let resolver = peeked.1.steal(); - let lint_store = &peeked.2; let hir = Steal::new(resolver.borrow_mut().access(|resolver| { passes::lower_to_hir( self.session(), - lint_store, + self.cstore(), resolver, &*self.dep_graph()?.peek(), &krate ) })?); - Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) + Ok((hir, BoxedResolver::to_expansion_result(resolver))) }) } pub fn prepare_outputs(&self) -> Result<&Query> { self.queries.prepare_outputs.compute(|| { - let expansion_result = self.expansion()?; - let (krate, boxed_resolver, _) = &*expansion_result.peek(); + let krate = self.expansion()?; + let krate = krate.peek(); let crate_name = self.crate_name()?; let crate_name = crate_name.peek(); - passes::prepare_outputs(self.session(), self, &krate, &boxed_resolver, &crate_name) + passes::prepare_outputs(self.session(), self, &krate.0, &*crate_name) }) } @@ -228,15 +212,14 @@ impl Compiler { self.queries.global_ctxt.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let outputs = self.prepare_outputs()?.peek().clone(); - let lint_store = self.expansion()?.peek().2.clone(); let hir = self.lower_to_hir()?; let hir = hir.peek(); - let (hir_forest, resolver_outputs) = &*hir; + let (ref hir_forest, ref expansion) = *hir; Ok(passes::create_global_ctxt( self, - lint_store, hir_forest.steal(), - resolver_outputs.steal(), + expansion.defs.steal(), + expansion.resolutions.steal(), outputs, &crate_name)) }) diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 8f11dc9372728..72df875fc8f4f 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -13,6 +13,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_errors::registry::Registry; +use rustc_lint; use rustc_metadata::dynamic_lib::DynamicLibrary; use rustc_mir; use rustc_passes; @@ -107,6 +108,11 @@ pub fn create_session( let codegen_backend = get_codegen_backend(&sess); + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); + if sess.unstable_options() { + rustc_lint::register_internals(&mut sess.lint_store.borrow_mut(), Some(&sess)); + } + let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg)); add_configuration(&mut cfg, &sess, &*codegen_backend); sess.parse_sess.config = cfg; @@ -167,7 +173,7 @@ pub fn scoped_thread R + Send, R: Send>(cfg: thread::Builder, f: #[cfg(not(parallel_compiler))] pub fn spawn_thread_pool R + Send, R: Send>( edition: Edition, - _threads: usize, + _threads: Option, stderr: &Option>>>, f: F, ) -> R { @@ -192,19 +198,18 @@ pub fn spawn_thread_pool R + Send, R: Send>( #[cfg(parallel_compiler)] pub fn spawn_thread_pool R + Send, R: Send>( edition: Edition, - threads: usize, + threads: Option, stderr: &Option>>>, f: F, ) -> R { - use rayon::{ThreadBuilder, ThreadPool, ThreadPoolBuilder}; + use rayon::{ThreadPool, ThreadPoolBuilder}; let gcx_ptr = &Lock::new(0); let mut config = ThreadPoolBuilder::new() - .thread_name(|_| "rustc".to_string()) .acquire_thread_handler(jobserver::acquire_thread) .release_thread_handler(jobserver::release_thread) - .num_threads(threads) + .num_threads(Session::threads_from_count(threads)) .deadlock_handler(|| unsafe { ty::query::handle_deadlock() }); if let Some(size) = get_stack_size() { @@ -220,20 +225,20 @@ pub fn spawn_thread_pool R + Send, R: Send>( // the thread local rustc uses. syntax_globals and syntax_pos_globals are // captured and set on the new threads. ty::tls::with_thread_locals sets up // thread local callbacks from libsyntax - let main_handler = move |thread: ThreadBuilder| { + let main_handler = move |worker: &mut dyn FnMut()| { syntax::GLOBALS.set(syntax_globals, || { syntax_pos::GLOBALS.set(syntax_pos_globals, || { if let Some(stderr) = stderr { io::set_panic(Some(box Sink(stderr.clone()))); } ty::tls::with_thread_locals(|| { - ty::tls::GCX_PTR.set(gcx_ptr, || thread.run()) + ty::tls::GCX_PTR.set(gcx_ptr, || worker()) }) }) }) }; - config.build_scoped(main_handler, with_pool).unwrap() + ThreadPool::scoped_pool(config, main_handler, with_pool).unwrap() }) }) }) @@ -497,7 +502,7 @@ pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguat // into various other hashes quite a bit (symbol hashes, incr. comp. hashes, // debuginfo type IDs, etc), so we don't want it to be too wide. 128 bits // should still be safe enough to avoid collisions in practice. - let mut hasher = StableHasher::new(); + let mut hasher = StableHasher::::new(); let mut metadata = session.opts.cg.metadata.clone(); // We don't want the crate_disambiguator to dependent on the order @@ -523,7 +528,7 @@ pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguat .contains(&config::CrateType::Executable); hasher.write(if is_exe { b"exe" } else { b"lib" }); - CrateDisambiguator::from(hasher.finish::()) + CrateDisambiguator::from(hasher.finish()) } pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml index a61a314d5492d..041d0aaead913 100644 --- a/src/librustc_lint/Cargo.toml +++ b/src/librustc_lint/Cargo.toml @@ -15,4 +15,3 @@ rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } rustc_data_structures = { path = "../librustc_data_structures" } -rustc_index = { path = "../librustc_index" } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ad674911e6f33..d0a7eab071c31 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -27,7 +27,6 @@ use rustc::hir::def::{Res, DefKind}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::ty::{self, Ty, TyCtxt, layout::VariantIdx}; use rustc::{lint, util}; -use rustc::lint::FutureIncompatibleInfo; use hir::Node; use util::nodemap::HirIdSet; use lint::{LateContext, LintContext, LintArray}; @@ -46,7 +45,7 @@ use syntax::feature_gate::{Stability, deprecated_attributes}; use syntax_pos::{BytePos, Span}; use syntax::symbol::{Symbol, kw, sym}; use syntax::errors::{Applicability, DiagnosticBuilder}; -use syntax::print::pprust::{self, expr_to_string}; +use syntax::print::pprust::expr_to_string; use syntax::visit::FnKind; use rustc::hir::{self, GenericParamKind, PatKind}; @@ -281,7 +280,7 @@ declare_lint! { pub MISSING_DOCS, Allow, "detects missing documentation for public members", - report_in_external_macro + report_in_external_macro: true } pub struct MissingDoc { @@ -602,11 +601,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations { declare_lint! { pub ANONYMOUS_PARAMETERS, Allow, - "detects anonymous parameters", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #41686 ", - edition: Some(Edition::Edition2018), - }; + "detects anonymous parameters" } declare_lint_pass!( @@ -706,8 +701,7 @@ impl EarlyLintPass for DeprecatedAttr { } } if attr.check_name(sym::no_start) || attr.check_name(sym::crate_id) { - let path_str = pprust::path_to_string(&attr.path); - let msg = format!("use of deprecated attribute `{}`: no longer used.", path_str); + let msg = format!("use of deprecated attribute `{}`: no longer used.", attr.path); lint_deprecated_attr(cx, attr, &msg, None); } } @@ -985,6 +979,35 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures { } } +declare_lint! { + UNIONS_WITH_DROP_FIELDS, + Warn, + "use of unions that contain fields with possibly non-trivial drop code" +} + +declare_lint_pass!( + /// Lint for unions that contain fields with possibly non-trivial destructors. + UnionsWithDropFields => [UNIONS_WITH_DROP_FIELDS] +); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields { + fn check_item(&mut self, ctx: &LateContext<'_, '_>, item: &hir::Item) { + if let hir::ItemKind::Union(ref vdata, _) = item.kind { + for field in vdata.fields() { + let field_ty = ctx.tcx.type_of( + ctx.tcx.hir().local_def_id(field.hir_id)); + if field_ty.needs_drop(ctx.tcx, ctx.param_env) { + ctx.span_lint(UNIONS_WITH_DROP_FIELDS, + field.span, + "union contains a field with possibly non-trivial drop code, \ + drop code of union fields is ignored when dropping the union"); + return; + } + } + } + } +} + declare_lint! { pub UNREACHABLE_PUB, Allow, @@ -1217,7 +1240,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints { if cx.tcx.features().trivial_bounds { let def_id = cx.tcx.hir().local_def_id(item.hir_id); let predicates = cx.tcx.predicates_of(def_id); - for &(predicate, span) in predicates.predicates { + for &(predicate, span) in &predicates.predicates { let predicate_kind_name = match predicate { Trait(..) => "Trait", TypeOutlives(..) | @@ -1264,6 +1287,7 @@ declare_lint_pass!( NO_MANGLE_GENERIC_ITEMS, MUTABLE_TRANSMUTES, UNSTABLE_FEATURES, + UNIONS_WITH_DROP_FIELDS, UNREACHABLE_PUB, TYPE_ALIAS_BOUNDS, TRIVIAL_BOUNDS @@ -1349,7 +1373,7 @@ declare_lint! { UNNAMEABLE_TEST_ITEMS, Warn, "detects an item that cannot be named being marked as `#[test_case]`", - report_in_external_macro + report_in_external_macro: true } pub struct UnnameableTestItems { @@ -1398,11 +1422,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems { declare_lint! { pub KEYWORD_IDENTS, Allow, - "detects edition keywords being used as an identifier", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #49716 ", - edition: Some(Edition::Edition2018), - }; + "detects edition keywords being used as an identifier" } declare_lint_pass!( diff --git a/src/librustc_lint/error_codes.rs b/src/librustc_lint/error_codes.rs index 2edc8fadf4568..ea2e1d9ecc53f 100644 --- a/src/librustc_lint/error_codes.rs +++ b/src/librustc_lint/error_codes.rs @@ -1,4 +1,4 @@ syntax::register_diagnostics! { ; -// E0721, // `await` keyword + E0721, // `await` keyword } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index b1beef04c5929..0e054013cd779 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -33,21 +33,27 @@ use rustc::lint; use rustc::lint::{EarlyContext, LateContext, LateLintPass, EarlyLintPass, LintPass, LintArray}; use rustc::lint::builtin::{ BARE_TRAIT_OBJECTS, + ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS, INTRA_DOC_LINK_RESOLUTION_FAILURE, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS, + parser::ILL_FORMED_ATTRIBUTE_INPUT, }; +use rustc::session; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use syntax::ast; +use syntax::edition::Edition; use syntax_pos::Span; +use session::Session; use lint::LintId; +use lint::FutureIncompatibleInfo; use redundant_semicolon::*; use nonstandard_style::*; @@ -158,6 +164,9 @@ macro_rules! late_lint_mod_passes { // Depends on referenced function signatures in expressions MutableTransmutes: MutableTransmutes, + // Depends on types of fields, checks if they implement Drop + UnionsWithDropFields: UnionsWithDropFields, + TypeAliasBounds: TypeAliasBounds, TrivialConstraints: TrivialConstraints, @@ -186,60 +195,59 @@ late_lint_passes!(declare_combined_late_pass, [pub BuiltinCombinedLateLintPass]) late_lint_mod_passes!(declare_combined_late_pass, [BuiltinCombinedModuleLateLintPass]); -pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> lint::LintStore { - let mut lint_store = lint::LintStore::new(); - - register_builtins(&mut lint_store, no_interleave_lints); - if internal_lints { - register_internals(&mut lint_store); - } - - lint_store -} - /// Tell the `LintStore` about all the built-in lints (the ones /// defined in this crate and the ones defined in /// `rustc::lint::builtin`). -fn register_builtins(store: &mut lint::LintStore, no_interleave_lints: bool) { +pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { macro_rules! add_lint_group { - ($name:expr, $($lint:ident),*) => ( - store.register_group(false, $name, None, vec![$(LintId::of($lint)),*]); + ($sess:ident, $name:expr, $($lint:ident),*) => ( + store.register_group($sess, false, $name, None, vec![$(LintId::of($lint)),*]); ) } macro_rules! register_pass { - ($method:ident, $ty:ident, $constructor:expr) => ( - store.register_lints(&$ty::get_lints()); - store.$method(|| box $constructor); + ($method:ident, $constructor:expr, [$($args:expr),*]) => ( + store.$method(sess, false, false, $($args,)* box $constructor); ) } macro_rules! register_passes { - ($method:ident, [$($passes:ident: $constructor:expr,)*]) => ( + ([$method:ident, $args:tt], [$($passes:ident: $constructor:expr,)*]) => ( $( - register_pass!($method, $passes, $constructor); + register_pass!($method, $constructor, $args); )* ) } - if no_interleave_lints { - pre_expansion_lint_passes!(register_passes, register_pre_expansion_pass); - early_lint_passes!(register_passes, register_early_pass); - late_lint_passes!(register_passes, register_late_pass); - late_lint_mod_passes!(register_passes, register_late_mod_pass); + if sess.map(|sess| sess.opts.debugging_opts.no_interleave_lints).unwrap_or(false) { + pre_expansion_lint_passes!(register_passes, [register_pre_expansion_pass, []]); + early_lint_passes!(register_passes, [register_early_pass, []]); + late_lint_passes!(register_passes, [register_late_pass, [false]]); + late_lint_mod_passes!(register_passes, [register_late_pass, [true]]); } else { - store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints()); - store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints()); - store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints()); - store.register_lints(&BuiltinCombinedLateLintPass::get_lints()); + store.register_pre_expansion_pass( + sess, + false, + true, + box BuiltinCombinedPreExpansionLintPass::new() + ); + store.register_early_pass(sess, false, true, box BuiltinCombinedEarlyLintPass::new()); + store.register_late_pass( + sess, false, true, true, box BuiltinCombinedModuleLateLintPass::new() + ); + store.register_late_pass( + sess, false, true, false, box BuiltinCombinedLateLintPass::new() + ); } - add_lint_group!("nonstandard_style", + add_lint_group!(sess, + "nonstandard_style", NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPER_CASE_GLOBALS); - add_lint_group!("unused", + add_lint_group!(sess, + "unused", UNUSED_IMPORTS, UNUSED_VARIABLES, UNUSED_ASSIGNMENTS, @@ -247,7 +255,6 @@ fn register_builtins(store: &mut lint::LintStore, no_interleave_lints: bool) { UNUSED_MUT, UNREACHABLE_CODE, UNREACHABLE_PATTERNS, - OVERLAPPING_PATTERNS, UNUSED_MUST_USE, UNUSED_UNSAFE, PATH_STATEMENTS, @@ -260,7 +267,8 @@ fn register_builtins(store: &mut lint::LintStore, no_interleave_lints: bool) { UNUSED_LABELS, UNUSED_PARENS); - add_lint_group!("rust_2018_idioms", + add_lint_group!(sess, + "rust_2018_idioms", BARE_TRAIT_OBJECTS, UNUSED_EXTERN_CRATES, ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, @@ -276,11 +284,165 @@ fn register_builtins(store: &mut lint::LintStore, no_interleave_lints: bool) { // MACRO_USE_EXTERN_CRATE, ); - add_lint_group!("rustdoc", + add_lint_group!(sess, + "rustdoc", INTRA_DOC_LINK_RESOLUTION_FAILURE, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS); + // Guidelines for creating a future incompatibility lint: + // + // - Create a lint defaulting to warn as normal, with ideally the same error + // message you would normally give + // - Add a suitable reference, typically an RFC or tracking issue. Go ahead + // and include the full URL, sort items in ascending order of issue numbers. + // - Later, change lint to error + // - Eventually, remove lint + store.register_future_incompatible(sess, vec![ + FutureIncompatibleInfo { + id: LintId::of(PRIVATE_IN_PUBLIC), + reference: "issue #34537 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE), + reference: "issue #34537 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY), + reference: "issue #35203 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(DUPLICATE_MACRO_EXPORTS), + reference: "issue #35896 ", + edition: Some(Edition::Edition2018), + }, + FutureIncompatibleInfo { + id: LintId::of(KEYWORD_IDENTS), + reference: "issue #49716 ", + edition: Some(Edition::Edition2018), + }, + FutureIncompatibleInfo { + id: LintId::of(SAFE_EXTERN_STATICS), + reference: "issue #36247 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(INVALID_TYPE_PARAM_DEFAULT), + reference: "issue #36887 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(LEGACY_DIRECTORY_OWNERSHIP), + reference: "issue #37872 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY), + reference: "issue #39207 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(MISSING_FRAGMENT_SPECIFIER), + reference: "issue #40107 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN), + reference: "issue #41620 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(ANONYMOUS_PARAMETERS), + reference: "issue #41686 ", + edition: Some(Edition::Edition2018), + }, + FutureIncompatibleInfo { + id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES), + reference: "issue #42238 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS), + reference: "issue #42868 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(SAFE_PACKED_BORROWS), + reference: "issue #46043 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(ORDER_DEPENDENT_TRAIT_OBJECTS), + reference: "issue #56484 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(TYVAR_BEHIND_RAW_POINTER), + reference: "issue #46906 ", + edition: Some(Edition::Edition2018), + }, + FutureIncompatibleInfo { + id: LintId::of(UNSTABLE_NAME_COLLISIONS), + reference: "issue #48919 ", + edition: None, + // Note: this item represents future incompatibility of all unstable functions in the + // standard library, and thus should never be removed or changed to an error. + }, + FutureIncompatibleInfo { + id: LintId::of(ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE), + reference: "issue #53130 ", + edition: Some(Edition::Edition2018), + }, + FutureIncompatibleInfo { + id: LintId::of(WHERE_CLAUSES_OBJECT_SAFETY), + reference: "issue #51443 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(PROC_MACRO_DERIVE_RESOLUTION_FALLBACK), + reference: "issue #50504 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS), + reference: "issue #52234 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(ILL_FORMED_ATTRIBUTE_INPUT), + reference: "issue #57571 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(AMBIGUOUS_ASSOCIATED_ITEMS), + reference: "issue #57644 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(NESTED_IMPL_TRAIT), + reference: "issue #59014 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(MUTABLE_BORROW_RESERVATION_CONFLICT), + reference: "issue #59159 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(INDIRECT_STRUCTURAL_MATCH), + reference: "issue #62411 ", + edition: None, + }, + FutureIncompatibleInfo { + id: LintId::of(SOFT_UNSTABLE), + reference: "issue #64266 ", + edition: None, + }, + ]); + // Register renamed and removed lints. store.register_renamed("single_use_lifetime", "single_use_lifetimes"); store.register_renamed("elided_lifetime_in_path", "elided_lifetimes_in_paths"); @@ -336,14 +498,12 @@ fn register_builtins(store: &mut lint::LintStore, no_interleave_lints: bool) { "converted into hard error, see https://github.com/rust-lang/rust/issues/46205"); } -fn register_internals(store: &mut lint::LintStore) { - store.register_lints(&DefaultHashTypes::get_lints()); - store.register_early_pass(|| box DefaultHashTypes::new()); - store.register_lints(&LintPassImpl::get_lints()); - store.register_early_pass(|| box LintPassImpl); - store.register_lints(&TyTyKind::get_lints()); - store.register_late_pass(|| box TyTyKind); +pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) { + store.register_early_pass(sess, false, false, box DefaultHashTypes::new()); + store.register_early_pass(sess, false, false, box LintPassImpl); + store.register_late_pass(sess, false, false, false, box TyTyKind); store.register_group( + sess, false, "rustc::internal", None, diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index aa6dfa50dddf3..e4567dc8265d8 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -7,7 +7,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx, SizeSkeleton}; use rustc::{lint, util}; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use util::nodemap::FxHashSet; use lint::{LateContext, LintContext, LintArray}; use lint::{LintPass, LateLintPass}; @@ -631,16 +631,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } - let is_non_exhaustive = - def.non_enum_variant().is_field_list_non_exhaustive(); - if is_non_exhaustive && !def.did.is_local() { - return FfiUnsafe { - ty, - reason: "this struct is non-exhaustive", - help: None, - }; - } - if def.non_enum_variant().fields.is_empty() { return FfiUnsafe { ty, @@ -740,25 +730,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } } - if def.is_variant_list_non_exhaustive() && !def.did.is_local() { - return FfiUnsafe { - ty, - reason: "this enum is non-exhaustive", - help: None, - }; - } - // Check the contained variants. for variant in &def.variants { - let is_non_exhaustive = variant.is_field_list_non_exhaustive(); - if is_non_exhaustive && !variant.def_id.is_local() { - return FfiUnsafe { - ty, - reason: "this enum has non-exhaustive variants", - help: None, - }; - } - for field in &variant.fields { let field_ty = cx.normalize_erasing_regions( ParamEnv::reveal_all(), @@ -971,8 +944,15 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let def_id = self.cx.tcx.hir().local_def_id(id); let sig = self.cx.tcx.fn_sig(def_id); let sig = self.cx.tcx.erase_late_bound_regions(&sig); + let inputs = if sig.c_variadic { + // Don't include the spoofed `VaListImpl` in the functions list + // of inputs. + &sig.inputs()[..sig.inputs().len() - 1] + } else { + &sig.inputs()[..] + }; - for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) { + for (input_ty, input_hir) in inputs.iter().zip(&decl.inputs) { self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty); } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 61b8cbe369aab..3b3995832cb4c 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -25,7 +25,7 @@ declare_lint! { pub UNUSED_MUST_USE, Warn, "unused result of a type flagged as `#[must_use]`", - report_in_external_macro + report_in_external_macro: true } declare_lint! { @@ -156,7 +156,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { } ty::Opaque(def, _) => { let mut has_emitted = false; - for (predicate, _) in cx.tcx.predicates_of(def).predicates { + for (predicate, _) in &cx.tcx.predicates_of(def).predicates { if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate { let trait_ref = poly_trait_predicate.skip_binder().trait_ref; let def_id = trait_ref.def_id; diff --git a/src/librustc_macros/Cargo.toml b/src/librustc_macros/Cargo.toml index c28fcb1a395ff..f989ebc6dfd8e 100644 --- a/src/librustc_macros/Cargo.toml +++ b/src/librustc_macros/Cargo.toml @@ -8,8 +8,8 @@ edition = "2018" proc-macro = true [dependencies] -synstructure = "0.12.1" -syn = { version = "1", features = ["full"] } -proc-macro2 = "1" -quote = "1" +synstructure = "0.10.2" +syn = { version = "0.15.22", features = ["full"] } +proc-macro2 = "0.4.24" +quote = "0.6.10" itertools = "0.8" diff --git a/src/librustc_macros/src/hash_stable.rs b/src/librustc_macros/src/hash_stable.rs index 735cfb11b365c..6d7590c7d1cd3 100644 --- a/src/librustc_macros/src/hash_stable.rs +++ b/src/librustc_macros/src/hash_stable.rs @@ -15,22 +15,22 @@ fn parse_attributes(field: &syn::Field) -> Attributes { }; for attr in &field.attrs { if let Ok(meta) = attr.parse_meta() { - if !meta.path().is_ident("stable_hasher") { + if &meta.name().to_string() != "stable_hasher" { continue; } let mut any_attr = false; if let Meta::List(list) = meta { for nested in list.nested.iter() { if let NestedMeta::Meta(meta) = nested { - if meta.path().is_ident("ignore") { + if &meta.name().to_string() == "ignore" { attrs.ignore = true; any_attr = true; } - if meta.path().is_ident("project") { + if &meta.name().to_string() == "project" { if let Meta::List(list) = meta { if let Some(nested) = list.nested.iter().next() { if let NestedMeta::Meta(meta) = nested { - attrs.project = meta.path().get_ident().cloned(); + attrs.project = Some(meta.name()); any_attr = true; } } @@ -76,10 +76,10 @@ pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::To s.bound_impl(quote!(::rustc_data_structures::stable_hasher::HashStable <::rustc::ich::StableHashingContext<'__ctx>>), quote!{ - fn hash_stable( + fn hash_stable<__W: ::rustc_data_structures::stable_hasher::StableHasherResult>( &self, __hcx: &mut ::rustc::ich::StableHashingContext<'__ctx>, - __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { + __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<__W>) { #discriminant match *self { #body } } diff --git a/src/librustc_macros/src/lib.rs b/src/librustc_macros/src/lib.rs index 0540c95d3ded3..3d3a020ef0c8e 100644 --- a/src/librustc_macros/src/lib.rs +++ b/src/librustc_macros/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(proc_macro_hygiene)] #![allow(rustc::default_hash_types)] #![recursion_limit="128"] diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs index 139e1b554cf90..9a68dd0f5e3ce 100644 --- a/src/librustc_macros/src/query.rs +++ b/src/librustc_macros/src/query.rs @@ -495,11 +495,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { dep_node_force_stream.extend(quote! { DepKind::#name => { if let Some(key) = RecoverKey::recover($tcx, $dep_node) { - $tcx.force_query::>( - key, - DUMMY_SP, - *$dep_node - ); + force_ex!($tcx, #name, key); } else { return false; } diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index 18192e35f8a20..5ff60a9267bad 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -18,9 +18,7 @@ rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_target = { path = "../librustc_target" } -rustc_index = { path = "../librustc_index" } rustc_serialize = { path = "../libserialize", package = "serialize" } stable_deref_trait = "1.0.0" syntax = { path = "../libsyntax" } -syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index f0a68058de8ca..682835d81a62b 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -1,49 +1,48 @@ //! Validates all used crates and extern libraries and loads their metadata -use crate::cstore::{self, CStore, MetadataBlob}; +use crate::cstore::{self, CStore, CrateSource, MetadataBlob}; use crate::locator::{self, CratePaths}; -use crate::schema::{CrateRoot, CrateDep}; -use rustc_data_structures::sync::{RwLock, Lock, AtomicCell}; +use crate::schema::{CrateRoot}; +use rustc_data_structures::sync::{Lrc, RwLock, Lock}; use rustc::hir::def_id::CrateNum; use rustc_data_structures::svh::Svh; -use rustc::dep_graph::DepNodeIndex; use rustc::middle::cstore::DepKind; use rustc::mir::interpret::AllocDecodingState; use rustc::session::{Session, CrateDisambiguator}; use rustc::session::config::{Sanitizer, self}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc::session::search_paths::PathKind; -use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn}; +use rustc::middle::cstore::{ExternCrate, ExternCrateSource}; use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; use rustc::hir::map::Definitions; use rustc::hir::def_id::LOCAL_CRATE; -use std::path::Path; +use std::ops::Deref; +use std::path::PathBuf; use std::{cmp, fs}; use syntax::ast; use syntax::attr; -use syntax_expand::allocator::{global_allocator_spans, AllocatorKind}; +use syntax::ext::allocator::{global_allocator_spans, AllocatorKind}; use syntax::symbol::{Symbol, sym}; -use syntax::span_fatal; +use syntax::{span_err, span_fatal}; use syntax_pos::{Span, DUMMY_SP}; use log::{debug, info, log_enabled}; use proc_macro::bridge::client::ProcMacro; -crate struct Library { - pub source: CrateSource, +pub struct Library { + pub dylib: Option<(PathBuf, PathKind)>, + pub rlib: Option<(PathBuf, PathKind)>, + pub rmeta: Option<(PathBuf, PathKind)>, pub metadata: MetadataBlob, } pub struct CrateLoader<'a> { - // Immutable configuration. - sess: &'a Session, - metadata_loader: &'a MetadataLoaderDyn, + pub sess: &'a Session, + cstore: &'a CStore, local_crate_name: Symbol, - // Mutable output. - cstore: CStore, } fn dump_crates(cstore: &CStore) { @@ -60,6 +59,29 @@ fn dump_crates(cstore: &CStore) { }); } +// Extra info about a crate loaded for plugins or exported macros. +struct ExtensionCrate { + metadata: PMDSource, + dylib: Option, + target_only: bool, +} + +enum PMDSource { + Registered(Lrc), + Owned(Library), +} + +impl Deref for PMDSource { + type Target = MetadataBlob; + + fn deref(&self) -> &MetadataBlob { + match *self { + PMDSource::Registered(ref cmd) => &cmd.blob, + PMDSource::Owned(ref lib) => &lib.metadata + } + } +} + enum LoadResult { Previous(CrateNum), Loaded(Library), @@ -78,32 +100,19 @@ impl<'a> LoadError<'a> { } impl<'a> CrateLoader<'a> { - pub fn new( - sess: &'a Session, - metadata_loader: &'a MetadataLoaderDyn, - local_crate_name: &str, - ) -> Self { + pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self { CrateLoader { sess, - metadata_loader, + cstore, local_crate_name: Symbol::intern(local_crate_name), - cstore: Default::default(), } } - pub fn cstore(&self) -> &CStore { - &self.cstore - } - - pub fn into_cstore(self) -> CStore { - self.cstore - } - fn existing_match(&self, name: Symbol, hash: Option<&Svh>, kind: PathKind) -> Option { let mut ret = None; self.cstore.iter_crate_data(|cnum, data| { - if data.root.name != name { return } + if data.name != name { return } match hash { Some(hash) if *hash == data.root.hash => { ret = Some(cnum); return } @@ -181,50 +190,54 @@ impl<'a> CrateLoader<'a> { fn register_crate( &mut self, host_lib: Option, - root: Option<&CratePaths>, + root: &Option, + ident: Symbol, span: Span, lib: Library, dep_kind: DepKind, name: Symbol - ) -> CrateNum { - let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate"); - - let Library { source, metadata } = lib; - let crate_root = metadata.get_root(); + ) -> (CrateNum, Lrc) { + let crate_root = lib.metadata.get_root(); self.verify_no_symbol_conflicts(span, &crate_root); let private_dep = self.sess.opts.externs.get(&name.as_str()) .map(|e| e.is_private_dep) .unwrap_or(false); - info!("register crate `{}` (private_dep = {})", crate_root.name, private_dep); + info!("register crate `extern crate {} as {}` (private_dep = {})", + crate_root.name, ident, private_dep); + // Claim this crate number and cache it let cnum = self.cstore.alloc_new_crate_num(); - // Maintain a reference to the top most crate. // Stash paths for top-most crate locally if necessary. - let crate_paths; - let root = if let Some(root) = root { - root + let crate_paths = if root.is_none() { + Some(CratePaths { + ident: ident.to_string(), + dylib: lib.dylib.clone().map(|p| p.0), + rlib: lib.rlib.clone().map(|p| p.0), + rmeta: lib.rmeta.clone().map(|p| p.0), + }) } else { - crate_paths = CratePaths { name: crate_root.name, source: source.clone() }; - &crate_paths + None }; + // Maintain a reference to the top most crate. + let root = if root.is_some() { root } else { &crate_paths }; + let Library { dylib, rlib, rmeta, metadata } = lib; let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind); let dependencies: Vec = cnum_map.iter().cloned().collect(); let raw_proc_macros = crate_root.proc_macro_data.map(|_| { - let temp_root; - let (dlsym_source, dlsym_root) = match &host_lib { - Some(host_lib) => - (&host_lib.source, { temp_root = host_lib.metadata.get_root(); &temp_root }), - None => (&source, &crate_root), - }; - let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate"); - self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator, span) + if self.sess.opts.debugging_opts.dual_proc_macros { + 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.dlsym_proc_macros(dylib.clone().map(|p| p.0), &crate_root, span) + } }); let interpret_alloc_index: Vec = crate_root.interpret_alloc_index @@ -240,9 +253,11 @@ impl<'a> CrateLoader<'a> { crate_root.def_path_table.decode((&metadata, self.sess)) }); - self.cstore.set_crate_data(cnum, cstore::CrateMetadata { + let cmeta = cstore::CrateMetadata { + name: crate_root.name, + imported_name: ident, extern_crate: Lock::new(None), - def_path_table, + def_path_table: Lrc::new(def_path_table), trait_impls, root: crate_root, blob: metadata, @@ -252,17 +267,24 @@ impl<'a> CrateLoader<'a> { source_map_import_info: RwLock::new(vec![]), alloc_decoding_state: AllocDecodingState::new(interpret_alloc_index), dep_kind: Lock::new(dep_kind), - source, + source: cstore::CrateSource { + dylib, + rlib, + rmeta, + }, private_dep, - raw_proc_macros, - dep_node_index: AtomicCell::new(DepNodeIndex::INVALID), - }); + span, + host_lib, + raw_proc_macros + }; - cnum + let cmeta = Lrc::new(cmeta); + self.cstore.set_crate_data(cnum, cmeta.clone()); + (cnum, cmeta) } fn load_proc_macro<'b>( - &self, + &mut self, locate_ctxt: &mut locator::Context<'b>, path_kind: PathKind, ) -> Option<(LoadResult, Option)> @@ -318,27 +340,16 @@ impl<'a> CrateLoader<'a> { fn resolve_crate<'b>( &'b mut self, + root: &'b Option, + ident: Symbol, name: Symbol, + hash: Option<&'b Svh>, + extra_filename: Option<&'b str>, span: Span, - dep_kind: DepKind, - dep: Option<(&'b CratePaths, &'b CrateDep)>, - ) -> CrateNum { - self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report()) - } - - fn maybe_resolve_crate<'b>( - &'b mut self, - name: Symbol, - span: Span, + path_kind: PathKind, mut dep_kind: DepKind, - dep: Option<(&'b CratePaths, &'b CrateDep)>, - ) -> Result> { - info!("resolving crate `{}`", name); - let (root, hash, extra_filename, path_kind) = match dep { - Some((root, dep)) => - (Some(root), Some(&dep.hash), Some(&dep.extra_filename[..]), PathKind::Dependency), - None => (None, None, None, PathKind::Crate), - }; + ) -> Result<(CrateNum, Lrc), LoadError<'b>> { + info!("resolving crate `extern crate {} as {}`", name, ident); let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { (LoadResult::Previous(cnum), None) } else { @@ -346,6 +357,7 @@ impl<'a> CrateLoader<'a> { let mut locate_ctxt = locator::Context { sess: self.sess, span, + ident, crate_name: name, hash, extra_filename, @@ -360,7 +372,7 @@ impl<'a> CrateLoader<'a> { rejected_via_filename: vec![], should_match_name: true, is_proc_macro: Some(false), - metadata_loader: self.metadata_loader, + metadata_loader: &*self.cstore.metadata_loader, }; self.load(&mut locate_ctxt).map(|r| (r, None)).or_else(|| { @@ -378,16 +390,16 @@ impl<'a> CrateLoader<'a> { data.dep_kind.with_lock(|data_dep_kind| { *data_dep_kind = cmp::max(*data_dep_kind, dep_kind); }); - Ok(cnum) + Ok((cnum, data)) } (LoadResult::Loaded(library), host_library) => { - Ok(self.register_crate(host_library, root, span, library, dep_kind, name)) + Ok(self.register_crate(host_library, root, ident, span, library, dep_kind, name)) } _ => panic!() } } - fn load(&self, locate_ctxt: &mut locator::Context<'_>) -> Option { + fn load(&mut self, locate_ctxt: &mut locator::Context<'_>) -> Option { let library = locate_ctxt.maybe_load_library_crate()?; // In the case that we're loading a crate, but not matching @@ -414,7 +426,7 @@ impl<'a> CrateLoader<'a> { } } - fn update_extern_crate(&self, + fn update_extern_crate(&mut self, cnum: CrateNum, mut extern_crate: ExternCrate, visited: &mut FxHashSet<(CrateNum, bool)>) @@ -457,7 +469,7 @@ impl<'a> CrateLoader<'a> { // Go through the crate metadata and load any crates that it references fn resolve_crate_deps(&mut self, - root: &CratePaths, + root: &Option, crate_root: &CrateRoot<'_>, metadata: &MetadataBlob, krate: CrateNum, @@ -472,7 +484,9 @@ impl<'a> CrateLoader<'a> { // The map from crate numbers in the crate we're resolving to local crate numbers. // We map 0 and all other holes in the map to our parent crate. The "additional" // self-dependencies should be harmless. - std::iter::once(krate).chain(crate_root.crate_deps.decode(metadata).map(|dep| { + std::iter::once(krate).chain(crate_root.crate_deps + .decode(metadata) + .map(|dep| { info!("resolving dep crate {} hash: `{}` extra filename: `{}`", dep.name, dep.hash, dep.extra_filename); if dep.kind == DepKind::UnexportedMacrosOnly { @@ -482,18 +496,91 @@ impl<'a> CrateLoader<'a> { DepKind::MacrosOnly => DepKind::MacrosOnly, _ => dep.kind, }; - self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep))) + let (local_cnum, ..) = self.resolve_crate( + root, dep.name, dep.name, Some(&dep.hash), Some(&dep.extra_filename), span, + PathKind::Dependency, dep_kind, + ).unwrap_or_else(|err| err.report()); + local_cnum })).collect() } + fn read_extension_crate(&mut self, span: Span, orig_name: Symbol, rename: Symbol) + -> ExtensionCrate { + info!("read extension crate `extern crate {} as {}`", orig_name, rename); + let target_triple = self.sess.opts.target_triple.clone(); + let host_triple = TargetTriple::from_triple(config::host_triple()); + let is_cross = target_triple != host_triple; + let mut target_only = false; + let mut locate_ctxt = locator::Context { + sess: self.sess, + span, + ident: orig_name, + crate_name: rename, + hash: None, + extra_filename: None, + filesearch: self.sess.host_filesearch(PathKind::Crate), + target: &self.sess.host, + triple: host_triple, + root: &None, + rejected_via_hash: vec![], + rejected_via_triple: vec![], + rejected_via_kind: vec![], + rejected_via_version: vec![], + rejected_via_filename: vec![], + should_match_name: true, + is_proc_macro: None, + metadata_loader: &*self.cstore.metadata_loader, + }; + let library = self.load(&mut locate_ctxt).or_else(|| { + if !is_cross { + return None + } + // Try loading from target crates. This will abort later if we + // try to load a plugin registrar function, + target_only = true; + + locate_ctxt.target = &self.sess.target.target; + locate_ctxt.triple = target_triple; + locate_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate); + + self.load(&mut locate_ctxt) + }); + let library = match library { + Some(l) => l, + None => locate_ctxt.report_errs(), + }; + + let (dylib, metadata) = match library { + LoadResult::Previous(cnum) => { + let data = self.cstore.get_crate_data(cnum); + (data.source.dylib.clone(), PMDSource::Registered(data)) + } + LoadResult::Loaded(library) => { + let dylib = library.dylib.clone(); + let metadata = PMDSource::Owned(library); + (dylib, metadata) + } + }; + + ExtensionCrate { + metadata, + dylib: dylib.map(|p| p.0), + target_only, + } + } + fn dlsym_proc_macros(&self, - path: &Path, - disambiguator: CrateDisambiguator, + dylib: Option, + root: &CrateRoot<'_>, span: Span ) -> &'static [ProcMacro] { use std::env; use crate::dynamic_lib::DynamicLibrary; + let path = match dylib { + Some(dylib) => dylib, + None => span_bug!(span, "proc-macro crate not dylib"), + }; // Make sure the path contains a / or the linker will search for it. let path = env::current_dir().unwrap().join(path); let lib = match DynamicLibrary::open(Some(&path)) { @@ -501,7 +588,7 @@ impl<'a> CrateLoader<'a> { Err(err) => self.sess.span_fatal(span, &err), }; - let sym = self.sess.generate_proc_macro_decls_symbol(disambiguator); + let sym = self.sess.generate_proc_macro_decls_symbol(root.disambiguator); let decls = unsafe { let sym = match lib.symbol(&sym) { Ok(f) => f, @@ -517,6 +604,41 @@ impl<'a> CrateLoader<'a> { decls } + /// Look for a plugin registrar. Returns library path, crate + /// SVH and DefIndex of the registrar function. + pub fn find_plugin_registrar(&mut self, + span: Span, + name: Symbol) + -> Option<(PathBuf, CrateDisambiguator)> { + let ekrate = self.read_extension_crate(span, name, name); + + if ekrate.target_only { + // Need to abort before syntax expansion. + let message = format!("plugin `{}` is not available for triple `{}` \ + (only found {})", + name, + config::host_triple(), + self.sess.opts.target_triple); + span_fatal!(self.sess, span, E0456, "{}", &message); + } + + let root = ekrate.metadata.get_root(); + match ekrate.dylib.as_ref() { + Some(dylib) => { + Some((dylib.to_path_buf(), root.disambiguator)) + } + None => { + span_err!(self.sess, span, E0457, + "plugin `{}` only found in rlib format, but must be available \ + in dylib format", + name); + // No need to abort because the loading code will just ignore this + // empty dylib. + None + } + } + } + fn inject_panic_runtime(&mut self, krate: &ast::Crate) { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. @@ -579,8 +701,10 @@ impl<'a> CrateLoader<'a> { }; info!("panic runtime not found -- loading {}", name); - let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None); - let data = self.cstore.get_crate_data(cnum); + let dep_kind = DepKind::Implicit; + let (cnum, data) = + self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind) + .unwrap_or_else(|err| err.report()); // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. @@ -631,10 +755,10 @@ impl<'a> CrateLoader<'a> { if !self.sess.crate_types.borrow().iter().all(|ct| { match *ct { // Link the runtime + config::CrateType::Staticlib | config::CrateType::Executable => true, // This crate will be compiled with the required // instrumentation pass - config::CrateType::Staticlib | config::CrateType::Rlib | config::CrateType::Dylib | config::CrateType::Cdylib => @@ -670,22 +794,26 @@ impl<'a> CrateLoader<'a> { let mut uses_std = false; self.cstore.iter_crate_data(|_, data| { - if data.root.name == sym::std { + if data.name == sym::std { uses_std = true; } }); if uses_std { - let name = Symbol::intern(match sanitizer { + let name = match *sanitizer { Sanitizer::Address => "rustc_asan", Sanitizer::Leak => "rustc_lsan", Sanitizer::Memory => "rustc_msan", Sanitizer::Thread => "rustc_tsan", - }); + }; info!("loading sanitizer: {}", name); - let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Explicit, None); - let data = self.cstore.get_crate_data(cnum); + let symbol = Symbol::intern(name); + let dep_kind = DepKind::Explicit; + let (_, data) = + self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, + PathKind::Crate, dep_kind) + .unwrap_or_else(|err| err.report()); // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime if !data.root.sanitizer_runtime { @@ -704,9 +832,12 @@ impl<'a> CrateLoader<'a> { { info!("loading profiler"); - let name = Symbol::intern("profiler_builtins"); - let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None); - let data = self.cstore.get_crate_data(cnum); + let symbol = Symbol::intern("profiler_builtins"); + let dep_kind = DepKind::Implicit; + let (_, data) = + self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, + PathKind::Crate, dep_kind) + .unwrap_or_else(|err| err.report()); // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.root.profiler_runtime { @@ -716,7 +847,7 @@ impl<'a> CrateLoader<'a> { } } - fn inject_allocator_crate(&self, krate: &ast::Crate) { + fn inject_allocator_crate(&mut self, krate: &ast::Crate) { let has_global_allocator = match &*global_allocator_spans(krate) { [span1, span2, ..] => { self.sess.struct_span_err(*span2, "cannot define multiple global allocators") @@ -852,7 +983,9 @@ impl<'a> CrateLoader<'a> { data.dependencies.borrow_mut().push(krate); }); } +} +impl<'a> CrateLoader<'a> { pub fn postprocess(&mut self, krate: &ast::Crate) { self.inject_sanitizer_runtime(); self.inject_profiler_runtime(); @@ -865,15 +998,13 @@ impl<'a> CrateLoader<'a> { } pub fn process_extern_crate( - &mut self, - item: &ast::Item, - definitions: &Definitions, + &mut self, item: &ast::Item, definitions: &Definitions, ) -> CrateNum { match item.kind { ast::ItemKind::ExternCrate(orig_name) => { debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", item.ident, orig_name); - let name = match orig_name { + let orig_name = match orig_name { Some(orig_name) => { crate::validate_crate_name(Some(self.sess), &orig_name.as_str(), Some(item.span)); @@ -887,7 +1018,10 @@ impl<'a> CrateLoader<'a> { DepKind::Explicit }; - let cnum = self.resolve_crate(name, item.span, dep_kind, None); + let (cnum, ..) = self.resolve_crate( + &None, item.ident.name, orig_name, None, None, + item.span, PathKind::Crate, dep_kind, + ).unwrap_or_else(|err| err.report()); let def_id = definitions.opt_local_def_id(item.id).unwrap(); let path_len = definitions.def_path(def_id.index).data.len(); @@ -901,14 +1035,21 @@ impl<'a> CrateLoader<'a> { }, &mut FxHashSet::default(), ); + self.cstore.add_extern_mod_stmt_cnum(item.id, cnum); cnum } _ => bug!(), } } - pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum { - let cnum = self.resolve_crate(name, span, DepKind::Explicit, None); + pub fn process_path_extern( + &mut self, + name: Symbol, + span: Span, + ) -> CrateNum { + let cnum = self.resolve_crate( + &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit + ).unwrap_or_else(|err| err.report()).0; self.update_extern_crate( cnum, @@ -925,8 +1066,14 @@ impl<'a> CrateLoader<'a> { cnum } - pub fn maybe_process_path_extern(&mut self, name: Symbol, span: Span) -> Option { - let cnum = self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()?; + pub fn maybe_process_path_extern( + &mut self, + name: Symbol, + span: Span, + ) -> Option { + let cnum = self.resolve_crate( + &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit + ).ok()?.0; self.update_extern_crate( cnum, diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 6b06cf575edcf..5bf4067431f24 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -2,19 +2,22 @@ // crates and libraries use crate::schema; -use rustc::dep_graph::DepNodeIndex; use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::map::definitions::DefPathTable; -use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate}; +use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader}; use rustc::mir::interpret::AllocDecodingState; -use rustc_index::vec::IndexVec; -use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::sync::{Lrc, RwLock, Lock, MetadataRef, AtomicCell}; +use rustc_data_structures::indexed_vec::IndexVec; +use rustc::util::nodemap::{FxHashMap, NodeMap}; + +use rustc_data_structures::sync::{Lrc, RwLock, Lock}; use syntax::ast; -use syntax::edition::Edition; -use syntax_expand::base::SyntaxExtension; +use syntax::ext::base::SyntaxExtension; +use syntax::symbol::Symbol; use syntax_pos; -use proc_macro::bridge::client::ProcMacro; + +pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference}; +pub use rustc::middle::cstore::NativeLibraryKind::*; +pub use rustc::middle::cstore::{CrateSource, LibSource, ForeignModule}; pub use crate::cstore_impl::{provide, provide_extern}; @@ -22,13 +25,18 @@ pub use crate::cstore_impl::{provide, provide_extern}; // local crate numbers (as generated during this session). Each external // crate may refer to types in other external crates, and each has their // own crate numbers. -crate type CrateNumMap = IndexVec; +pub type CrateNumMap = IndexVec; -crate struct MetadataBlob(pub MetadataRef); +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); /// Holds information about a syntax_pos::SourceFile imported from another crate. /// See `imported_source_files()` for more information. -crate struct ImportedSourceFile { +pub struct ImportedSourceFile { /// This SourceFile's byte-offset within the source_map of its original crate pub original_start_pos: syntax_pos::BytePos, /// The end of this SourceFile within the source_map of its original crate @@ -37,120 +45,119 @@ crate struct ImportedSourceFile { pub translated_source_file: Lrc, } -crate struct CrateMetadata { - /// The primary crate data - binary metadata blob. - crate blob: MetadataBlob, +pub struct CrateMetadata { + /// Original name of the crate. + pub name: Symbol, + + /// Name of the crate as imported. I.e., if imported with + /// `extern crate foo as bar;` this will be `bar`. + pub imported_name: Symbol, - // --- Some data pre-decoded from the metadata blob, usually for performance --- + /// Information about the extern crate that caused this crate to + /// be loaded. If this is `None`, then the crate was injected + /// (e.g., by the allocator) + pub extern_crate: Lock>, + + pub blob: MetadataBlob, + pub cnum_map: CrateNumMap, + pub cnum: CrateNum, + pub dependencies: Lock>, + pub source_map_import_info: RwLock>, + + /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. + pub alloc_decoding_state: AllocDecodingState, + + // NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this + // 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>, - /// Properties of the whole crate. - /// NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this - /// 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. - crate root: schema::CrateRoot<'static>, /// 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. - crate def_path_table: DefPathTable, - /// Trait impl data. - /// FIXME: Used only from queries and can use query cache, - /// so pre-decoding can probably be avoided. - crate trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>, - /// Proc macro descriptions for this crate, if it's a proc macro crate. - crate raw_proc_macros: Option<&'static [ProcMacro]>, - /// Source maps for code from the crate. - crate source_map_import_info: RwLock>, - /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. - crate alloc_decoding_state: AllocDecodingState, - /// The `DepNodeIndex` of the `DepNode` representing this upstream crate. - /// It is initialized on the first access in `get_crate_dep_node_index()`. - /// Do not access the value directly, as it might not have been initialized yet. - /// The field must always be initialized to `DepNodeIndex::INVALID`. - crate dep_node_index: AtomicCell, - - // --- Other significant crate properties --- - - /// ID of this crate, from the current compilation session's point of view. - crate cnum: CrateNum, - /// Maps crate IDs as they are were seen from this crate's compilation sessions into - /// IDs as they are seen from the current compilation session. - crate cnum_map: CrateNumMap, - /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime. - crate dependencies: Lock>, - /// How to link (or not link) this crate to the currently compiled crate. - crate dep_kind: Lock, - /// Filesystem location of this crate. - crate source: CrateSource, + pub def_path_table: Lrc, + + pub trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>, + + pub dep_kind: Lock, + pub source: CrateSource, + /// Whether or not this crate should be consider a private dependency /// for purposes of the 'exported_private_dependencies' lint - crate private_dep: bool, + pub private_dep: bool, - // --- Data used only for improving diagnostics --- + pub host_lib: Option, + pub span: Span, - /// Information about the `extern crate` item or path that caused this crate to be loaded. - /// If this is `None`, then the crate was injected (e.g., by the allocator). - crate extern_crate: Lock>, + pub raw_proc_macros: Option<&'static [ProcMacro]>, } -#[derive(Clone)] pub struct CStore { - metas: IndexVec>>, + metas: RwLock>>>, + /// Map from NodeId's of local extern crate statements to crate numbers + extern_mod_crate_map: Lock>, + pub metadata_loader: Box, } pub enum LoadedMacro { - MacroDef(ast::Item, Edition), + MacroDef(ast::Item), ProcMacro(SyntaxExtension), } -impl Default for CStore { - fn default() -> Self { +impl CStore { + pub fn new(metadata_loader: Box) -> CStore { CStore { // We add an empty entry for LOCAL_CRATE (which maps to zero) in // order to make array indices in `metas` match with the // corresponding `CrateNum`. This first entry will always remain // `None`. - metas: IndexVec::from_elem_n(None, 1), + metas: RwLock::new(IndexVec::from_elem_n(None, 1)), + extern_mod_crate_map: Default::default(), + metadata_loader, } } -} -impl CStore { - crate fn alloc_new_crate_num(&mut self) -> CrateNum { - self.metas.push(None); - CrateNum::new(self.metas.len() - 1) + pub(super) fn alloc_new_crate_num(&self) -> CrateNum { + let mut metas = self.metas.borrow_mut(); + let cnum = CrateNum::new(metas.len()); + metas.push(None); + cnum } - crate fn get_crate_data(&self, cnum: CrateNum) -> &CrateMetadata { - self.metas[cnum].as_ref() + pub(super) fn get_crate_data(&self, cnum: CrateNum) -> Lrc { + self.metas.borrow()[cnum].clone() .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum)) } - crate fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) { - assert!(self.metas[cnum].is_none(), "Overwriting crate metadata entry"); - self.metas[cnum] = Some(Lrc::new(data)); + pub(super) fn set_crate_data(&self, cnum: CrateNum, data: Lrc) { + let mut metas = self.metas.borrow_mut(); + assert!(metas[cnum].is_none(), "Overwriting crate metadata entry"); + metas[cnum] = Some(data); } - crate fn iter_crate_data(&self, mut i: I) - where I: FnMut(CrateNum, &CrateMetadata) + pub(super) fn iter_crate_data(&self, mut i: I) + where I: FnMut(CrateNum, &Lrc) { - for (k, v) in self.metas.iter_enumerated() { + for (k, v) in self.metas.borrow().iter_enumerated() { if let &Some(ref v) = v { i(k, v); } } } - crate fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec { + pub(super) fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec { let mut ordering = Vec::new(); self.push_dependencies_in_postorder(&mut ordering, krate); ordering.reverse(); ordering } - crate fn push_dependencies_in_postorder(&self, ordering: &mut Vec, krate: CrateNum) { + pub(super) fn push_dependencies_in_postorder(&self, + ordering: &mut Vec, + krate: CrateNum) { if ordering.contains(&krate) { return; } @@ -165,13 +172,21 @@ impl CStore { ordering.push(krate); } - crate fn do_postorder_cnums_untracked(&self) -> Vec { + pub(super) fn do_postorder_cnums_untracked(&self) -> Vec { let mut ordering = Vec::new(); - for (num, v) in self.metas.iter_enumerated() { + for (num, v) in self.metas.borrow().iter_enumerated() { if let &Some(_) = v { self.push_dependencies_in_postorder(&mut ordering, num); } } return ordering } + + pub(super) fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) { + self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum); + } + + pub(super) fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { + self.extern_mod_crate_map.borrow().get(&emod_id).cloned() + } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index d942a19194a14..83182df31cf52 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -6,7 +6,8 @@ use crate::foreign_modules; use crate::schema; use rustc::ty::query::QueryConfig; -use rustc::middle::cstore::{CrateSource, CrateStore, DepKind, EncodedMetadata, NativeLibraryKind}; +use rustc::middle::cstore::{CrateStore, DepKind, + EncodedMetadata, NativeLibraryKind}; use rustc::middle::exported_symbols::ExportedSymbol; use rustc::middle::stability::DeprecationEntry; use rustc::middle::dependency_format::Linkage; @@ -29,12 +30,12 @@ use std::sync::Arc; use syntax::ast; use syntax::attr; use syntax::source_map; +use syntax::edition::Edition; use syntax::parse::source_file_to_stream; use syntax::parse::parser::emit_unclosed_delims; -use syntax::source_map::Spanned; use syntax::symbol::Symbol; use syntax_pos::{Span, FileName}; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; macro_rules! provide { (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, @@ -46,22 +47,23 @@ macro_rules! provide { $tcx: TyCtxt<$lt>, def_id_arg: T, ) -> as QueryConfig<$lt>>::Value { - let _prof_timer = - $tcx.prof.generic_activity("metadata_decode_entry"); - #[allow(unused_variables)] let ($def_id, $other) = def_id_arg.into_args(); assert!(!$def_id.is_local()); - let $cdata = $tcx.crate_data_as_any($def_id.krate); + let def_path_hash = $tcx.def_path_hash(DefId { + krate: $def_id.krate, + index: CRATE_DEF_INDEX + }); + let dep_node = def_path_hash + .to_dep_node(rustc::dep_graph::DepKind::CrateMetadata); + // The DepNodeIndex of the DepNode::CrateMetadata should be + // cached somewhere, so that we can use read_index(). + $tcx.dep_graph.read(dep_node); + + let $cdata = $tcx.crate_data_as_rc_any($def_id.krate); let $cdata = $cdata.downcast_ref::() .expect("CrateStore created data is not a CrateMetadata"); - - if $tcx.dep_graph.is_fully_enabled() { - let crate_dep_node_index = $cdata.get_crate_dep_node_index($tcx); - $tcx.dep_graph.read_index(crate_dep_node_index); - } - $compute })* @@ -96,9 +98,11 @@ provide! { <'tcx> tcx, def_id, other, cdata, generics_of => { tcx.arena.alloc(cdata.get_generics(def_id.index, tcx.sess)) } - predicates_of => { cdata.get_predicates(def_id.index, tcx) } - predicates_defined_on => { cdata.get_predicates_defined_on(def_id.index, tcx) } - super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) } + predicates_of => { tcx.arena.alloc(cdata.get_predicates(def_id.index, tcx)) } + predicates_defined_on => { + tcx.arena.alloc(cdata.get_predicates_defined_on(def_id.index, tcx)) + } + super_predicates_of => { tcx.arena.alloc(cdata.get_super_predicates(def_id.index, tcx)) } trait_def => { tcx.arena.alloc(cdata.get_trait_def(def_id.index, tcx.sess)) } @@ -150,6 +154,9 @@ provide! { <'tcx> tcx, def_id, other, cdata, 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) } + const_is_rvalue_promotable_to_static => { + cdata.const_is_rvalue_promotable_to_static(def_id.index) + } is_mir_available => { cdata.is_item_mir_available(def_id.index) } dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) } @@ -213,7 +220,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, let r = *cdata.dep_kind.lock(); r } - crate_name => { cdata.root.name } + crate_name => { cdata.name } item_children => { let mut result = SmallVec::<[_; 8]>::new(); cdata.each_child_of_item(def_id.index, |child| result.push(child), tcx.sess); @@ -266,11 +273,7 @@ pub fn provide(providers: &mut Providers<'_>) { // resolve! Does this work? Unsure! That's what the issue is about *providers = Providers { is_dllimport_foreign_item: |tcx, id| { - match tcx.native_library_kind(id) { - Some(NativeLibraryKind::NativeUnknown) | - Some(NativeLibraryKind::NativeRawDylib) => true, - _ => false, - } + tcx.native_library_kind(id) == Some(NativeLibraryKind::NativeUnknown) }, is_statically_included_foreign_item: |tcx, id| { match tcx.native_library_kind(id) { @@ -410,8 +413,26 @@ impl cstore::CStore { } } - pub fn struct_field_names_untracked(&self, def: DefId, sess: &Session) -> Vec> { - self.get_crate_data(def.krate).get_struct_field_names(def.index, sess) + pub fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { + let data = self.get_crate_data(cnum); + let r = *data.dep_kind.lock(); + r + } + + pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition { + self.get_crate_data(cnum).root.edition + } + + pub fn struct_field_names_untracked(&self, def: DefId) -> Vec { + self.get_crate_data(def.krate).get_struct_field_names(def.index) + } + + pub fn ctor_kind_untracked(&self, def: DefId) -> def::CtorKind { + self.get_crate_data(def.krate).get_ctor_kind(def.index) + } + + pub fn item_attrs_untracked(&self, def: DefId, sess: &Session) -> Lrc<[ast::Attribute]> { + self.get_crate_data(def.krate).get_item_attrs(def.index, sess) } pub fn item_children_untracked( @@ -426,15 +447,14 @@ impl cstore::CStore { } pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { - let _prof_timer = sess.prof.generic_activity("metadata_load_macro"); - let data = self.get_crate_data(id.krate); 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.root.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); @@ -455,7 +475,7 @@ impl cstore::CStore { LoadedMacro::MacroDef(ast::Item { // FIXME: cross-crate hygiene - ident: ast::Ident::with_dummy_span(name), + ident: ast::Ident::with_dummy_span(name.as_symbol()), id: ast::DUMMY_NODE_ID, span: local_span, attrs: attrs.iter().cloned().collect(), @@ -465,21 +485,17 @@ impl cstore::CStore { }), vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited), tokens: None, - }, data.root.edition) + }) } pub fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssocItem { self.get_crate_data(def.krate).get_associated_item(def.index) } - - pub fn crate_source_untracked(&self, cnum: CrateNum) -> CrateSource { - self.get_crate_data(cnum).source.clone() - } } impl CrateStore for cstore::CStore { - fn crate_data_as_any(&self, cnum: CrateNum) -> &dyn Any { - self.get_crate_data(cnum) + fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc { + self.get_crate_data(krate) } fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics { @@ -488,7 +504,7 @@ impl CrateStore for cstore::CStore { fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { - self.get_crate_data(cnum).root.name + self.get_crate_data(cnum).name } fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool { @@ -509,10 +525,20 @@ impl CrateStore for cstore::CStore { /// parent `DefId` as well as some idea of what kind of data the /// `DefId` refers to. fn def_key(&self, def: DefId) -> DefKey { + // Note: loading the def-key (or def-path) for a def-id is not + // a *read* of its metadata. This is because the def-id is + // really just an interned shorthand for a def-path, which is the + // canonical name for an item. + // + // self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).def_key(def.index) } fn def_path(&self, def: DefId) -> DefPath { + // See `Note` above in `def_key()` for why this read is + // commented out: + // + // self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).def_path(def.index) } @@ -520,8 +546,8 @@ impl CrateStore for cstore::CStore { self.get_crate_data(def.krate).def_path_hash(def.index) } - fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable { - &self.get_crate_data(cnum).def_path_table + fn def_path_table(&self, cnum: CrateNum) -> Lrc { + self.get_crate_data(cnum).def_path_table.clone() } fn crates_untracked(&self) -> Vec @@ -531,6 +557,11 @@ impl CrateStore for cstore::CStore { result } + fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option + { + self.do_extern_mod_stmt_cnum(emod_id) + } + fn postorder_cnums_untracked(&self) -> Vec { self.do_postorder_cnums_untracked() } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 09ff7891a9deb..3c6a1c4744696 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1,20 +1,18 @@ // Decoding metadata from a single crate's metadata -use crate::cstore::{self, CrateMetadata, MetadataBlob}; +use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule}; use crate::schema::*; -use crate::table::{FixedSizeEncoding, PerDefTable}; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::{Lrc, ReadGuard}; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc::hir; -use rustc::middle::cstore::{LinkagePreference, NativeLibrary, ForeignModule}; +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_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; -use rustc::dep_graph::{DepNodeIndex, DepKind}; use rustc::middle::lang_items; use rustc::mir::{self, interpret}; use rustc::mir::interpret::AllocDecodingSession; @@ -26,21 +24,20 @@ use rustc::util::captures::Captures; use std::io; use std::mem; -use std::num::NonZeroUsize; use std::u32; -use rustc_serialize::{Decodable, Decoder, Encodable, SpecializedDecoder, opaque}; +use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, Ident}; -use syntax::source_map::{self, respan, Spanned}; +use syntax::source_map; use syntax::symbol::{Symbol, sym}; -use syntax_expand::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension}; -use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP}; +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_expand::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro}; +use syntax::ext::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro}; -crate struct DecodeContext<'a, 'tcx> { +pub struct DecodeContext<'a, 'tcx> { opaque: opaque::Decoder<'a>, cdata: Option<&'a CrateMetadata>, sess: Option<&'tcx Session>, @@ -56,7 +53,7 @@ crate struct DecodeContext<'a, 'tcx> { } /// Abstract over the various ways one can create metadata decoders. -crate trait Metadata<'a, 'tcx>: Copy { +pub trait Metadata<'a, 'tcx>: Copy { fn raw_bytes(self) -> &'a [u8]; fn cdata(self) -> Option<&'a CrateMetadata> { None } fn sess(self) -> Option<&'tcx Session> { None } @@ -131,31 +128,31 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) { } } -impl<'a, 'tcx, T: Encodable + Decodable> Lazy { - crate fn decode>(self, metadata: M) -> T { - let mut dcx = metadata.decoder(self.position.get()); +impl<'a, 'tcx, T: Decodable> Lazy { + pub fn decode>(self, meta: M) -> T { + let mut dcx = meta.decoder(self.position); dcx.lazy_state = LazyState::NodeStart(self.position); T::decode(&mut dcx).unwrap() } } -impl<'a: 'x, 'tcx: 'x, 'x, T: Encodable + Decodable> Lazy<[T]> { - crate fn decode>( +impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> { + pub fn decode>( self, - metadata: M, + meta: M, ) -> impl ExactSizeIterator + Captures<'a> + Captures<'tcx> + 'x { - let mut dcx = metadata.decoder(self.position.get()); + let mut dcx = meta.decoder(self.position); dcx.lazy_state = LazyState::NodeStart(self.position); (0..self.meta).map(move |_| T::decode(&mut dcx).unwrap()) } } impl<'a, 'tcx> DecodeContext<'a, 'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { + pub fn tcx(&self) -> TyCtxt<'tcx> { self.tcx.expect("missing TyCtxt in DecodeContext") } - fn cdata(&self) -> &'a CrateMetadata { + pub fn cdata(&self) -> &'a CrateMetadata { self.cdata.expect("missing CrateMetadata in DecodeContext") } @@ -168,14 +165,13 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { let position = match self.lazy_state { LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"), LazyState::NodeStart(start) => { - let start = start.get(); assert!(distance + min_size <= start); start - distance - min_size } - LazyState::Previous(last_min_end) => last_min_end.get() + distance, + LazyState::Previous(last_min_end) => last_min_end + distance, }; - self.lazy_state = LazyState::Previous(NonZeroUsize::new(position + min_size).unwrap()); - Ok(Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta)) + self.lazy_state = LazyState::Previous(position + min_size); + Ok(Lazy::from_position_and_meta(position, meta)) } } @@ -238,13 +234,13 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { } } -impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, 'tcx> { +impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { self.read_lazy_with_meta(()) } } -impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, 'tcx> { +impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { let len = self.read_usize()?; if len == 0 { @@ -255,14 +251,6 @@ impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, } } -impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> - where Option: FixedSizeEncoding, -{ - fn specialized_decode(&mut self) -> Result>, Self::Error> { - let len = self.read_usize()?; - self.read_lazy_with_meta(len) - } -} impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { #[inline] @@ -390,28 +378,24 @@ for DecodeContext<'a, 'tcx> { implement_ty_decoder!( DecodeContext<'a, 'tcx> ); impl<'tcx> MetadataBlob { - crate fn is_compatible(&self) -> bool { + pub fn is_compatible(&self) -> bool { self.raw_bytes().starts_with(METADATA_HEADER) } - crate fn get_rustc_version(&self) -> String { - Lazy::::from_position( - NonZeroUsize::new(METADATA_HEADER.len() + 4).unwrap(), - ).decode(self) + pub fn get_rustc_version(&self) -> String { + Lazy::::from_position(METADATA_HEADER.len() + 4).decode(self) } - crate fn get_root(&self) -> CrateRoot<'tcx> { + pub fn get_root(&self) -> CrateRoot<'tcx> { let slice = self.raw_bytes(); let offset = METADATA_HEADER.len(); 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::>::from_position( - NonZeroUsize::new(pos).unwrap(), - ).decode(self) + Lazy::>::from_position(pos).decode(self) } - crate fn list_crate_metadata(&self, + pub fn list_crate_metadata(&self, out: &mut dyn io::Write) -> io::Result<()> { write!(out, "=External Dependencies=\n")?; let root = self.get_root(); @@ -448,7 +432,7 @@ impl<'tcx> EntryKind<'tcx> { EntryKind::Mod(_) => DefKind::Mod, EntryKind::Variant(_) => DefKind::Variant, EntryKind::Trait(_) => DefKind::Trait, - EntryKind::TraitAlias => DefKind::TraitAlias, + EntryKind::TraitAlias(_) => DefKind::TraitAlias, EntryKind::Enum(..) => DefKind::Enum, EntryKind::MacroDef(_) => DefKind::Macro(MacroKind::Bang), EntryKind::ForeignType => DefKind::ForeignTy, @@ -458,13 +442,13 @@ impl<'tcx> EntryKind<'tcx> { EntryKind::Impl(_) | EntryKind::Field | EntryKind::Generator(_) | - EntryKind::Closure => return None, + EntryKind::Closure(_) => return None, }) } } impl<'a, 'tcx> CrateMetadata { - crate fn is_proc_macro_crate(&self) -> bool { + pub fn is_proc_macro_crate(&self) -> bool { self.root.proc_macro_decls_static.is_some() } @@ -473,20 +457,27 @@ impl<'a, 'tcx> CrateMetadata { self.root.proc_macro_data.unwrap().decode(self).find(|x| *x == id).is_some() } - fn maybe_kind(&self, item_id: DefIndex) -> Option> { - self.root.per_def.kind.get(self, item_id).map(|k| k.decode(self)) + 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>> { + self.root.entries_index.lookup(self.blob.raw_bytes(), item_id) } - fn kind(&self, item_id: DefIndex) -> EntryKind<'tcx> { - assert!(!self.is_proc_macro(item_id)); - self.maybe_kind(item_id).unwrap_or_else(|| { - bug!( - "CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}", - item_id, - self.root.name, - self.cnum, - ) - }) + fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { + match self.maybe_entry(item_id) { + None => { + bug!("entry: id not found: {:?} in crate {:?} with number {}", + item_id, + self.name, + self.cnum) + } + Some(d) => d.decode(self), + } } fn local_def_id(&self, index: DefIndex) -> DefId { @@ -507,21 +498,22 @@ impl<'a, 'tcx> CrateMetadata { &self.raw_proc_macros.unwrap()[pos] } - crate fn item_name(&self, item_index: DefIndex) -> Symbol { + pub fn item_name(&self, item_index: DefIndex) -> 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()) } } - crate fn def_kind(&self, index: DefIndex) -> Option { + pub fn def_kind(&self, index: DefIndex) -> Option { if !self.is_proc_macro(index) { - self.kind(index).def_kind() + self.entry(index).kind.def_kind() } else { Some(DefKind::Macro( macro_kind(self.raw_proc_macro(index)) @@ -529,8 +521,8 @@ impl<'a, 'tcx> CrateMetadata { } } - crate fn get_span(&self, index: DefIndex, sess: &Session) -> Span { - self.root.per_def.span.get(self, index).unwrap().decode((self, sess)) + pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span { + self.entry(index).span.decode((self, sess)) } crate fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension { @@ -551,20 +543,25 @@ impl<'a, 'tcx> CrateMetadata { 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, - self.root.edition, + edition, Symbol::intern(name), - &self.get_item_attrs(id, sess), + &self.get_attributes(&self.entry(id), sess), ) } - crate fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { - match self.kind(item_id) { + pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { + match self.entry(item_id).kind { EntryKind::Trait(data) => { let data = data.decode((self, sess)); ty::TraitDef::new(self.local_def_id(item_id), @@ -574,7 +571,7 @@ impl<'a, 'tcx> CrateMetadata { data.is_marker, self.def_path_table.def_path_hash(item_id)) }, - EntryKind::TraitAlias => { + EntryKind::TraitAlias(_) => { ty::TraitDef::new(self.local_def_id(item_id), hir::Unsafety::Normal, false, @@ -589,24 +586,18 @@ impl<'a, 'tcx> CrateMetadata { fn get_variant( &self, tcx: TyCtxt<'tcx>, - kind: &EntryKind<'_>, + item: &Entry<'_>, index: DefIndex, parent_did: DefId, + adt_kind: ty::AdtKind, ) -> ty::VariantDef { - let data = match kind { + let data = match item.kind { EntryKind::Variant(data) | EntryKind::Struct(data, _) | EntryKind::Union(data, _) => data.decode(self), _ => bug!(), }; - let adt_kind = match kind { - EntryKind::Variant(_) => ty::AdtKind::Enum, - EntryKind::Struct(..) => ty::AdtKind::Struct, - EntryKind::Union(..) => ty::AdtKind::Union, - _ => bug!(), - }; - let variant_did = if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { @@ -620,12 +611,14 @@ impl<'a, 'tcx> CrateMetadata { variant_did, ctor_did, data.discr, - self.root.per_def.children.get(self, index).unwrap_or(Lazy::empty()) - .decode(self).map(|index| ty::FieldDef { + item.children.decode(self).map(|index| { + let f = self.entry(index); + ty::FieldDef { did: self.local_def_id(index), ident: Ident::with_dummy_span(self.item_name(index)), - vis: self.get_visibility(index), - }).collect(), + vis: f.visibility.decode(self) + } + }).collect(), data.ctor_kind, adt_kind, parent_did, @@ -633,115 +626,122 @@ impl<'a, 'tcx> CrateMetadata { ) } - crate fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef { - let kind = self.kind(item_id); + pub fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef { + let item = self.entry(item_id); let did = self.local_def_id(item_id); - let (adt_kind, repr) = match kind { + let (kind, repr) = match item.kind { EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr), EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr), EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr), _ => bug!("get_adt_def called on a non-ADT {:?}", did), }; - let variants = if let ty::AdtKind::Enum = adt_kind { - self.root.per_def.children.get(self, item_id).unwrap_or(Lazy::empty()) + let variants = if let ty::AdtKind::Enum = kind { + item.children .decode(self) .map(|index| { - self.get_variant(tcx, &self.kind(index), index, did) + self.get_variant(tcx, &self.entry(index), index, did, kind) }) .collect() } else { - std::iter::once(self.get_variant(tcx, &kind, item_id, did)).collect() + std::iter::once(self.get_variant(tcx, &item, item_id, did, kind)).collect() }; - tcx.alloc_adt_def(did, adt_kind, variants, repr) + tcx.alloc_adt_def(did, kind, variants, repr) } - crate fn get_predicates( + pub fn get_predicates( &self, item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { - self.root.per_def.predicates.get(self, item_id).unwrap().decode((self, tcx)) + self.entry(item_id).predicates.unwrap().decode((self, tcx)) } - crate fn get_predicates_defined_on( + pub fn get_predicates_defined_on( &self, item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { - self.root.per_def.predicates_defined_on.get(self, item_id).unwrap().decode((self, tcx)) + self.entry(item_id).predicates_defined_on.unwrap().decode((self, tcx)) } - crate fn get_super_predicates( + pub fn get_super_predicates( &self, item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { - self.root.per_def.super_predicates.get(self, item_id).unwrap().decode((self, tcx)) + let super_predicates = match self.entry(item_id).kind { + EntryKind::Trait(data) => data.decode(self).super_predicates, + EntryKind::TraitAlias(data) => data.decode(self).super_predicates, + _ => bug!("def-index does not refer to trait or trait alias"), + }; + + super_predicates.decode((self, tcx)) } - crate fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics { - self.root.per_def.generics.get(self, item_id).unwrap().decode((self, sess)) + pub fn get_generics(&self, + item_id: DefIndex, + sess: &Session) + -> ty::Generics { + self.entry(item_id).generics.unwrap().decode((self, sess)) } - crate fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - self.root.per_def.ty.get(self, id).unwrap().decode((self, tcx)) + pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + self.entry(id).ty.unwrap().decode((self, tcx)) } - crate fn get_stability(&self, id: DefIndex) -> Option { + pub fn get_stability(&self, id: DefIndex) -> Option { match self.is_proc_macro(id) { true => self.root.proc_macro_stability.clone(), - false => self.root.per_def.stability.get(self, id).map(|stab| stab.decode(self)), + false => self.entry(id).stability.map(|stab| stab.decode(self)), } } - crate fn get_deprecation(&self, id: DefIndex) -> Option { - self.root.per_def.deprecation.get(self, id) - .filter(|_| !self.is_proc_macro(id)) - .map(|depr| depr.decode(self)) + pub fn get_deprecation(&self, id: DefIndex) -> Option { + self.entry_unless_proc_macro(id) + .and_then(|entry| entry.deprecation.map(|depr| depr.decode(self))) } - crate fn get_visibility(&self, id: DefIndex) -> ty::Visibility { + pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility { match self.is_proc_macro(id) { true => ty::Visibility::Public, - false => self.root.per_def.visibility.get(self, id).unwrap().decode(self), + false => self.entry(id).visibility.decode(self), } } - fn get_impl_data(&self, id: DefIndex) -> ImplData { - match self.kind(id) { + fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { + match self.entry(id).kind { EntryKind::Impl(data) => data.decode(self), _ => bug!(), } } - crate fn get_parent_impl(&self, id: DefIndex) -> Option { + pub fn get_parent_impl(&self, id: DefIndex) -> Option { self.get_impl_data(id).parent_impl } - crate fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity { + pub fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity { self.get_impl_data(id).polarity } - crate fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness { + pub fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness { self.get_impl_data(id).defaultness } - crate fn get_coerce_unsized_info( - &self, - id: DefIndex, - ) -> Option { + pub fn get_coerce_unsized_info(&self, + id: DefIndex) + -> Option { self.get_impl_data(id).coerce_unsized_info } - crate fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option> { - self.root.per_def.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx))) + pub fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option> { + self.get_impl_data(id).trait_ref.map(|tr| tr.decode((self, tcx))) } /// Iterates over all the stability attributes in the given crate. - crate fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(ast::Name, Option)] { + pub fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(ast::Name, Option)] { // FIXME: For a proc macro crate, not sure whether we should return the "host" // features or an empty Vec. Both don't cause ICEs. tcx.arena.alloc_from_iter(self.root @@ -750,7 +750,7 @@ impl<'a, 'tcx> CrateMetadata { } /// Iterates over the language items in the given crate. - crate fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] { + pub fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] { if self.is_proc_macro_crate() { // Proc macro crates do not export any lang-items to the target. &[] @@ -763,7 +763,7 @@ impl<'a, 'tcx> CrateMetadata { } /// Iterates over the diagnostic items in the given crate. - crate fn get_diagnostic_items( + pub fn get_diagnostic_items( &self, tcx: TyCtxt<'tcx>, ) -> &'tcx FxHashMap { @@ -780,7 +780,7 @@ impl<'a, 'tcx> CrateMetadata { } /// Iterates over each child of the given item. - crate fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Session) + pub fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Session) where F: FnMut(def::Export) { if let Some(proc_macros_ids) = self.root.proc_macro_data.map(|d| d.decode(self)) { @@ -807,42 +807,38 @@ impl<'a, 'tcx> CrateMetadata { } // Find the item. - let kind = match self.maybe_kind(id) { + let item = match self.maybe_entry(id) { None => return, - Some(kind) => kind, + Some(item) => item.decode((self, sess)), }; // Iterate over all children. let macros_only = self.dep_kind.lock().macros_only(); - let children = self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty()); - for child_index in children.decode((self, sess)) { + for child_index in item.children.decode((self, sess)) { if macros_only { continue } // Get the item. - if let Some(child_kind) = self.maybe_kind(child_index) { - match child_kind { + if let Some(child) = self.maybe_entry(child_index) { + let child = child.decode((self, sess)); + match child.kind { EntryKind::MacroDef(..) => {} _ if macros_only => continue, _ => {} } // Hand off the item to the callback. - match child_kind { + match child.kind { // FIXME(eddyb) Don't encode these in children. EntryKind::ForeignMod => { - let child_children = - self.root.per_def.children.get(self, child_index) - .unwrap_or(Lazy::empty()); - for child_index in child_children.decode((self, sess)) { + for child_index in child.children.decode((self, sess)) { 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_dummy_span(self.item_name(child_index)), vis: self.get_visibility(child_index), - span: self.root.per_def.span.get(self, child_index).unwrap() - .decode((self, sess)), + span: self.entry(child_index).span.decode((self, sess)), }); } } @@ -854,10 +850,10 @@ impl<'a, 'tcx> CrateMetadata { } let def_key = self.def_key(child_index); - let span = self.get_span(child_index, sess); + let span = child.span.decode((self, sess)); if let (Some(kind), Some(name)) = (self.def_kind(child_index), def_key.disambiguated_data.data.get_opt_name()) { - let ident = Ident::with_dummy_span(name); + let ident = Ident::from_interned_str(name); let vis = self.get_visibility(child_index); let def_id = self.local_def_id(child_index); let res = Res::Def(kind, def_id); @@ -907,7 +903,7 @@ impl<'a, 'tcx> CrateMetadata { } } - if let EntryKind::Mod(data) = kind { + if let EntryKind::Mod(data) = item.kind { for exp in data.decode((self, sess)).reexports.decode((self, sess)) { match exp.res { Res::Def(DefKind::Macro(..), _) => {} @@ -919,35 +915,41 @@ impl<'a, 'tcx> CrateMetadata { } } - crate fn is_item_mir_available(&self, id: DefIndex) -> bool { + pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool { + match self.entry(id).kind { + EntryKind::AssocConst(_, data, _) | + EntryKind::Const(data, _) => data.ast_promotable, + _ => bug!(), + } + } + + pub fn is_item_mir_available(&self, id: DefIndex) -> bool { !self.is_proc_macro(id) && - self.root.per_def.mir.get(self, id).is_some() + self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some() } - crate fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { - self.root.per_def.mir.get(self, id) - .filter(|_| !self.is_proc_macro(id)) + 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)) + bug!("get_optimized_mir: missing MIR for `{:?}", self.local_def_id(id)) }) - .decode((self, tcx)) } - crate fn get_promoted_mir( + pub fn get_promoted_mir( &self, tcx: TyCtxt<'tcx>, id: DefIndex, ) -> IndexVec> { - self.root.per_def.promoted_mir.get(self, id) - .filter(|_| !self.is_proc_macro(id)) + 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)) }) - .decode((self, tcx)) } - crate fn mir_const_qualif(&self, id: DefIndex) -> u8 { - match self.kind(id) { + pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { + match self.entry(id).kind { EntryKind::Const(qualif, _) | EntryKind::AssocConst(AssocContainer::ImplDefault, qualif, _) | EntryKind::AssocConst(AssocContainer::ImplFinal, qualif, _) => { @@ -957,12 +959,13 @@ impl<'a, 'tcx> CrateMetadata { } } - crate fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem { + pub fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem { + let item = self.entry(id); let def_key = self.def_key(id); let parent = self.local_def_id(def_key.parent.unwrap()); let name = def_key.disambiguated_data.data.get_opt_name().unwrap(); - let (kind, container, has_self) = match self.kind(id) { + let (kind, container, has_self) = match item.kind { EntryKind::AssocConst(container, _, _) => { (ty::AssocKind::Const, container, false) } @@ -980,9 +983,9 @@ impl<'a, 'tcx> CrateMetadata { }; ty::AssocItem { - ident: Ident::with_dummy_span(name), + ident: Ident::from_interned_str(name), kind, - vis: self.get_visibility(id), + vis: item.visibility.decode(self), defaultness: container.defaultness(), def_id: self.local_def_id(id), container: container.with_def_id(parent), @@ -990,13 +993,12 @@ impl<'a, 'tcx> CrateMetadata { } } - crate fn get_item_variances(&self, id: DefIndex) -> Vec { - self.root.per_def.variances.get(self, id).unwrap_or(Lazy::empty()) - .decode(self).collect() + pub fn get_item_variances(&self, id: DefIndex) -> Vec { + self.entry(id).variances.decode(self).collect() } - crate fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { - match self.kind(node_id) { + pub fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { + match self.entry(node_id).kind { EntryKind::Struct(data, _) | EntryKind::Union(data, _) | EntryKind::Variant(data) => data.decode(self).ctor_kind, @@ -1004,8 +1006,8 @@ impl<'a, 'tcx> CrateMetadata { } } - crate fn get_ctor_def_id(&self, node_id: DefIndex) -> Option { - match self.kind(node_id) { + pub fn get_ctor_def_id(&self, node_id: DefIndex) -> Option { + match self.entry(node_id).kind { EntryKind::Struct(data, _) => { data.decode(self).ctor.map(|index| self.local_def_id(index)) } @@ -1016,7 +1018,8 @@ impl<'a, 'tcx> CrateMetadata { } } - crate fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> { + + 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 @@ -1027,22 +1030,22 @@ impl<'a, 'tcx> CrateMetadata { node_id }; - Lrc::from(self.root.per_def.attributes.get(self, item_id).unwrap_or(Lazy::empty()) - .decode((self, sess)) - .collect::>()) + let item = self.entry(item_id); + Lrc::from(self.get_attributes(&item, sess)) } - crate fn get_struct_field_names( - &self, - id: DefIndex, - sess: &Session, - ) -> Vec> { - self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty()) + pub fn get_struct_field_names(&self, id: DefIndex) -> Vec { + self.entry(id) + .children .decode(self) - .map(|index| respan(self.get_span(index, sess), self.item_name(index))) + .map(|index| self.item_name(index)) .collect() } + fn get_attributes(&self, item: &Entry<'tcx>, sess: &Session) -> Vec { + item.attributes.decode((self, sess)).collect() + } + // Translate a DefId from the current compilation environment to a DefId // for an external crate. fn reverse_translate_def_id(&self, did: DefId) -> Option { @@ -1058,19 +1061,18 @@ impl<'a, 'tcx> CrateMetadata { None } - crate fn get_inherent_implementations_for_type( + pub fn get_inherent_implementations_for_type( &self, tcx: TyCtxt<'tcx>, id: DefIndex, ) -> &'tcx [DefId] { - tcx.arena.alloc_from_iter( - self.root.per_def.inherent_impls.get(self, id).unwrap_or(Lazy::empty()) - .decode(self) - .map(|index| self.local_def_id(index)) - ) + tcx.arena.alloc_from_iter(self.entry(id) + .inherent_impls + .decode(self) + .map(|index| self.local_def_id(index))) } - crate fn get_implementations_for_trait( + pub fn get_implementations_for_trait( &self, tcx: TyCtxt<'tcx>, filter: Option, @@ -1101,7 +1103,7 @@ impl<'a, 'tcx> CrateMetadata { } } - crate fn get_trait_of_item(&self, id: DefIndex) -> Option { + pub fn get_trait_of_item(&self, id: DefIndex) -> Option { let def_key = self.def_key(id); match def_key.disambiguated_data.data { DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (), @@ -1109,16 +1111,16 @@ impl<'a, 'tcx> CrateMetadata { _ => return None, } def_key.parent.and_then(|parent_index| { - match self.kind(parent_index) { + match self.entry(parent_index).kind { EntryKind::Trait(_) | - EntryKind::TraitAlias => Some(self.local_def_id(parent_index)), + EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)), _ => None, } }) } - crate fn get_native_libraries(&self, sess: &Session) -> Vec { + pub fn get_native_libraries(&self, sess: &Session) -> Vec { if self.is_proc_macro_crate() { // Proc macro crates do not have any *target* native libraries. vec![] @@ -1127,7 +1129,7 @@ impl<'a, 'tcx> CrateMetadata { } } - crate fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] { + pub fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] { if self.is_proc_macro_crate() { // Proc macro crates do not have any *target* foreign modules. &[] @@ -1136,7 +1138,7 @@ impl<'a, 'tcx> CrateMetadata { } } - crate fn get_dylib_dependency_formats( + pub fn get_dylib_dependency_formats( &self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(CrateNum, LinkagePreference)] { @@ -1150,7 +1152,7 @@ impl<'a, 'tcx> CrateMetadata { })) } - crate fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] { + pub fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] { if self.is_proc_macro_crate() { // Proc macro crates do not depend on any target weak lang-items. &[] @@ -1161,8 +1163,8 @@ impl<'a, 'tcx> CrateMetadata { } } - crate fn get_fn_param_names(&self, id: DefIndex) -> Vec { - let param_names = match self.kind(id) { + 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).param_names, EntryKind::Method(data) => data.decode(self).fn_data.param_names, @@ -1171,7 +1173,7 @@ impl<'a, 'tcx> CrateMetadata { param_names.decode(self).collect() } - crate fn exported_symbols( + pub fn exported_symbols( &self, tcx: TyCtxt<'tcx>, ) -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> { @@ -1184,23 +1186,24 @@ impl<'a, 'tcx> CrateMetadata { } } - crate fn get_rendered_const(&self, id: DefIndex) -> String { - match self.kind(id) { + pub fn get_rendered_const(&self, id: DefIndex) -> String { + match self.entry(id).kind { EntryKind::Const(_, data) | EntryKind::AssocConst(_, _, data) => data.decode(self).0, _ => bug!(), } } - crate fn get_macro(&self, id: DefIndex) -> MacroDef { - match self.kind(id) { + pub fn get_macro(&self, id: DefIndex) -> MacroDef { + let entry = self.entry(id); + match entry.kind { EntryKind::MacroDef(macro_def) => macro_def.decode(self), _ => bug!(), } } crate fn is_const_fn_raw(&self, id: DefIndex) -> bool { - let constness = match self.kind(id) { + let constness = match self.entry(id).kind { EntryKind::Method(data) => data.decode(self).fn_data.constness, EntryKind::Fn(data) => data.decode(self).constness, EntryKind::Variant(..) | EntryKind::Struct(..) => hir::Constness::Const, @@ -1209,17 +1212,17 @@ impl<'a, 'tcx> CrateMetadata { constness == hir::Constness::Const } - crate fn asyncness(&self, id: DefIndex) -> hir::IsAsync { - match self.kind(id) { + 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: expected function kind"), + _ => bug!("asyncness: expect functions entry."), } } - crate fn is_foreign_item(&self, id: DefIndex) -> bool { - match self.kind(id) { + pub fn is_foreign_item(&self, id: DefIndex) -> bool { + match self.entry(id).kind { EntryKind::ForeignImmStatic | EntryKind::ForeignMutStatic | EntryKind::ForeignFn(_) => true, @@ -1228,7 +1231,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn static_mutability(&self, id: DefIndex) -> Option { - match self.kind(id) { + match self.entry(id).kind { EntryKind::ImmStatic | EntryKind::ForeignImmStatic => Some(hir::MutImmutable), EntryKind::MutStatic | @@ -1237,28 +1240,37 @@ impl<'a, 'tcx> CrateMetadata { } } - crate fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { - self.root.per_def.fn_sig.get(self, id).unwrap().decode((self, tcx)) + pub fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { + let sig = match self.entry(id).kind { + EntryKind::Fn(data) | + EntryKind::ForeignFn(data) => data.decode(self).sig, + EntryKind::Method(data) => data.decode(self).fn_data.sig, + EntryKind::Variant(data) | + EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(), + EntryKind::Closure(data) => data.decode(self).sig, + _ => bug!(), + }; + sig.decode((self, tcx)) } #[inline] - crate fn def_key(&self, index: DefIndex) -> DefKey { + pub fn def_key(&self, index: DefIndex) -> DefKey { 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(Symbol::intern(name)); + key.disambiguated_data.data = DefPathData::MacroNs(InternedString::intern(name)); } key } // Returns the path leading to the thing with this `id`. - crate fn def_path(&self, id: DefIndex) -> DefPath { + pub fn def_path(&self, id: DefIndex) -> DefPath { debug!("def_path(cnum={:?}, id={:?})", self.cnum, id); DefPath::make(self.cnum, id, |parent| self.def_key(parent)) } #[inline] - crate fn def_path_hash(&self, index: DefIndex) -> DefPathHash { + pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash { self.def_path_table.def_path_hash(index) } @@ -1287,10 +1299,9 @@ impl<'a, 'tcx> CrateMetadata { /// /// Proc macro crates don't currently export spans, so this function does not have /// to work for them. - fn imported_source_files( - &'a self, - local_source_map: &source_map::SourceMap, - ) -> ReadGuard<'a, Vec> { + pub fn imported_source_files(&'a self, + local_source_map: &source_map::SourceMap) + -> ReadGuard<'a, Vec> { { let source_files = self.source_map_import_info.borrow(); if !source_files.is_empty() { @@ -1319,7 +1330,6 @@ impl<'a, 'tcx> CrateMetadata { mut lines, mut multibyte_chars, mut non_narrow_chars, - mut normalized_pos, name_hash, .. } = source_file_to_import; @@ -1339,9 +1349,6 @@ impl<'a, 'tcx> CrateMetadata { for swc in &mut non_narrow_chars { *swc = *swc - start_pos; } - for np in &mut normalized_pos { - np.pos = np.pos - start_pos; - } let local_version = local_source_map.new_imported_source_file(name, name_was_remapped, @@ -1351,8 +1358,7 @@ impl<'a, 'tcx> CrateMetadata { source_length, lines, multibyte_chars, - non_narrow_chars, - normalized_pos); + non_narrow_chars); debug!("CrateMetaData::imported_source_files alloc \ source_file {:?} original (start_pos {:?} end_pos {:?}) \ translated (start_pos {:?} end_pos {:?})", @@ -1372,30 +1378,6 @@ impl<'a, 'tcx> CrateMetadata { // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref. self.source_map_import_info.borrow() } - - /// Get the `DepNodeIndex` corresponding this crate. The result of this - /// method is cached in the `dep_node_index` field. - pub(super) fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex { - let mut dep_node_index = self.dep_node_index.load(); - - if unlikely!(dep_node_index == DepNodeIndex::INVALID) { - // We have not cached the DepNodeIndex for this upstream crate yet, - // so use the dep-graph to find it out and cache it. - // Note that multiple threads can enter this block concurrently. - // That is fine because the DepNodeIndex remains constant - // throughout the whole compilation session, and multiple stores - // would always write the same value. - - let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX); - let dep_node = def_path_hash.to_dep_node(DepKind::CrateMetadata); - - dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node); - assert!(dep_node_index != DepNodeIndex::INVALID); - self.dep_node_index.store(dep_node_index); - } - - dep_node_index - } } // Cannot be implemented on 'ProcMacro', as libproc_macro diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs index 7f76a9730e198..9a30623b33d62 100644 --- a/src/librustc_metadata/dependency_format.rs +++ b/src/librustc_metadata/dependency_format.rs @@ -60,7 +60,7 @@ use rustc::ty::TyCtxt; use rustc::util::nodemap::FxHashMap; use rustc_target::spec::PanicStrategy; -crate fn calculate(tcx: TyCtxt<'_>) -> Dependencies { +pub fn calculate(tcx: TyCtxt<'_>) -> Dependencies { tcx.sess.crate_types.borrow().iter().map(|&ty| { let linkage = calculate_type(tcx, ty); verify_ok(tcx, &linkage); diff --git a/src/librustc_metadata/dynamic_lib.rs b/src/librustc_metadata/dynamic_lib.rs index 3871eb89f7b42..4c279361ff5e1 100644 --- a/src/librustc_metadata/dynamic_lib.rs +++ b/src/librustc_metadata/dynamic_lib.rs @@ -32,6 +32,30 @@ impl DynamicLibrary { } } + /// Loads a dynamic library into the global namespace (RTLD_GLOBAL on Unix) + /// and do it now (don't use RTLD_LAZY on Unix). + pub fn open_global_now(filename: &Path) -> Result { + let maybe_library = dl::open_global_now(filename.as_os_str()); + match maybe_library { + Err(err) => Err(err), + Ok(handle) => Ok(DynamicLibrary { handle }) + } + } + + /// Returns the environment variable for this process's dynamic library + /// search path + pub fn envvar() -> &'static str { + if cfg!(windows) { + "PATH" + } else if cfg!(target_os = "macos") { + "DYLD_LIBRARY_PATH" + } else if cfg!(target_os = "haiku") { + "LIBRARY_PATH" + } else { + "LD_LIBRARY_PATH" + } + } + /// Accesses the value at the symbol of the dynamic library. pub unsafe fn symbol(&self, symbol: &str) -> Result<*mut T, String> { // This function should have a lifetime constraint of 'a on @@ -59,7 +83,7 @@ mod dl { use std::ptr; use std::str; - pub(super) fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { + pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { check_for_errors_in(|| { unsafe { match filename { @@ -70,6 +94,13 @@ mod dl { }) } + pub fn open_global_now(filename: &OsStr) -> Result<*mut u8, String> { + check_for_errors_in(|| unsafe { + let s = CString::new(filename.as_bytes()).unwrap(); + libc::dlopen(s.as_ptr(), libc::RTLD_GLOBAL | libc::RTLD_NOW) as *mut u8 + }) + } + unsafe fn open_external(filename: &OsStr) -> *mut u8 { let s = CString::new(filename.as_bytes()).unwrap(); libc::dlopen(s.as_ptr(), libc::RTLD_LAZY) as *mut u8 @@ -79,8 +110,8 @@ mod dl { libc::dlopen(ptr::null(), libc::RTLD_LAZY) as *mut u8 } - fn check_for_errors_in(f: F) -> Result - where F: FnOnce() -> T, + pub fn check_for_errors_in(f: F) -> Result where + F: FnOnce() -> T, { use std::sync::{Mutex, Once}; static INIT: Once = Once::new(); @@ -108,15 +139,14 @@ mod dl { } } - pub(super) unsafe fn symbol( - handle: *mut u8, - symbol: *const libc::c_char, - ) -> Result<*mut u8, String> { + pub unsafe fn symbol(handle: *mut u8, + symbol: *const libc::c_char) + -> Result<*mut u8, String> { check_for_errors_in(|| { libc::dlsym(handle as *mut libc::c_void, symbol) as *mut u8 }) } - pub(super) unsafe fn close(handle: *mut u8) { + pub unsafe fn close(handle: *mut u8) { libc::dlclose(handle as *mut libc::c_void); () } } @@ -148,7 +178,11 @@ mod dl { fn FreeLibrary(handle: HMODULE) -> BOOL; } - pub(super) fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { + pub fn open_global_now(filename: &OsStr) -> Result<*mut u8, String> { + open(Some(filename)) + } + + pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { // disable "dll load failed" error dialog. let prev_error_mode = unsafe { // SEM_FAILCRITICALERRORS 0x01 @@ -191,15 +225,14 @@ mod dl { result } - pub(super) unsafe fn symbol( - handle: *mut u8, - symbol: *const c_char, - ) -> Result<*mut u8, String> { + pub unsafe fn symbol(handle: *mut u8, + symbol: *const c_char) + -> Result<*mut u8, String> { let ptr = GetProcAddress(handle as HMODULE, symbol) as *mut u8; ptr_result(ptr) } - pub(super) unsafe fn close(handle: *mut u8) { + pub unsafe fn close(handle: *mut u8) { FreeLibrary(handle as HMODULE); } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0dc9f91ae00e1..0bb4f52be14c2 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,21 +1,21 @@ +use crate::index::Index; use crate::schema::*; -use crate::table::{FixedSizeEncoding, PerDefTable}; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; use rustc::hir::def::CtorKind; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, LOCAL_CRATE}; -use rustc::hir::{GenericParamKind, AnonConst}; +use rustc::hir::GenericParamKind; use rustc::hir::map::definitions::DefPathTable; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc::middle::dependency_format::Linkage; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel, metadata_symbol_name}; use rustc::middle::lang_items; use rustc::mir::{self, interpret}; use rustc::traits::specialization_graph; -use rustc::ty::{self, Ty, TyCtxt, SymbolName}; +use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName}; use rustc::ty::codec::{self as ty_codec, TyEncoder}; use rustc::ty::layout::VariantIdx; @@ -23,16 +23,15 @@ use rustc::session::config::{self, CrateType}; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::sync::Lrc; use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; use std::hash::Hash; -use std::num::NonZeroUsize; use std::path::Path; +use rustc_data_structures::sync::Lrc; use std::u32; use syntax::ast; use syntax::attr; -use syntax_expand::proc_macro::is_proc_macro_attr; +use syntax::ext::proc_macro::is_proc_macro_attr; use syntax::source_map::Spanned; use syntax::symbol::{kw, sym, Ident, Symbol}; use syntax_pos::{self, FileName, SourceFile, Span}; @@ -43,11 +42,11 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; use rustc::hir::intravisit; -struct EncodeContext<'tcx> { +pub struct EncodeContext<'tcx> { opaque: opaque::Encoder, - tcx: TyCtxt<'tcx>, + pub tcx: TyCtxt<'tcx>, - per_def: PerDefTables<'tcx>, + entries_index: Index<'tcx>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -60,30 +59,6 @@ struct EncodeContext<'tcx> { source_file_cache: Lrc, } -#[derive(Default)] -struct PerDefTables<'tcx> { - kind: PerDefTable>>, - visibility: PerDefTable>, - span: PerDefTable>, - attributes: PerDefTable>, - children: PerDefTable>, - stability: PerDefTable>, - deprecation: PerDefTable>, - - ty: PerDefTable>>, - fn_sig: PerDefTable>>, - impl_trait_ref: PerDefTable>>, - inherent_impls: PerDefTable>, - variances: PerDefTable>, - generics: PerDefTable>, - predicates: PerDefTable>>, - predicates_defined_on: PerDefTable>>, - super_predicates: PerDefTable>>, - - mir: PerDefTable>>, - promoted_mir: PerDefTable>>>, -} - macro_rules! encoder_methods { ($($name:ident($ty:ty);)*) => { $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> { @@ -122,13 +97,13 @@ impl<'tcx> Encoder for EncodeContext<'tcx> { } } -impl<'tcx, T: Encodable> SpecializedEncoder> 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) } } -impl<'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'tcx> { +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 { @@ -138,15 +113,6 @@ impl<'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'tcx> { } } -impl<'tcx, T> SpecializedEncoder>> for EncodeContext<'tcx> - where Option: FixedSizeEncoding, -{ - fn specialized_encode(&mut self, lazy: &Lazy>) -> Result<(), Self::Error> { - self.emit_usize(lazy.meta)?; - self.emit_lazy_distance(*lazy) - } -} - impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { #[inline] fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> { @@ -246,11 +212,11 @@ impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { } } -impl<'tcx> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]> for EncodeContext<'tcx> { +impl<'tcx> SpecializedEncoder> for EncodeContext<'tcx> { fn specialized_encode(&mut self, - predicates: &&'tcx [(ty::Predicate<'tcx>, Span)]) + predicates: &ty::GenericPredicates<'tcx>) -> Result<(), Self::Error> { - ty_codec::encode_spanned_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands) + ty_codec::encode_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands) } } @@ -291,7 +257,7 @@ impl EncodeContentsForLazy for T { } } -impl EncodeContentsForLazy<[T]> for I +impl EncodeContentsForLazy<[T]> for I where I: IntoIterator, I::Item: EncodeContentsForLazy, { @@ -300,28 +266,15 @@ impl EncodeContentsForLazy<[T]> for I } } -// Shorthand for `$self.$tables.$table.set($key, $self.lazy($value))`, which would -// normally need extra variables to avoid errors about multiple mutable borrows. -macro_rules! record { - ($self:ident.$tables:ident.$table:ident[$key:expr] <- $value:expr) => {{ - { - let value = $value; - let lazy = $self.lazy(value); - $self.$tables.$table.set($key, lazy); - } - }} -} - impl<'tcx> EncodeContext<'tcx> { fn emit_lazy_distance( &mut self, lazy: Lazy, ) -> Result<(), ::Error> { - let min_end = lazy.position.get() + T::min_size(lazy.meta); + 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) => { - let start = start.get(); assert!(min_end <= start); start - min_end } @@ -331,10 +284,10 @@ impl<'tcx> EncodeContext<'tcx> { "make sure that the calls to `lazy*` \ are in the same order as the metadata fields", ); - lazy.position.get() - last_min_end.get() + lazy.position - last_min_end } }; - self.lazy_state = LazyState::Previous(NonZeroUsize::new(min_end).unwrap()); + self.lazy_state = LazyState::Previous(min_end); self.emit_usize(distance) } @@ -342,22 +295,42 @@ impl<'tcx> EncodeContext<'tcx> { &mut self, value: impl EncodeContentsForLazy, ) -> Lazy { - let pos = NonZeroUsize::new(self.position()).unwrap(); + let pos = self.position(); 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; - assert!(pos.get() + ::min_size(meta) <= self.position()); + assert!(pos + ::min_size(meta) <= self.position()); Lazy::from_position_and_meta(pos, meta) } + /// Emit the data for a `DefId` to the metadata. The function to + /// emit the data is `op`, and it will be given `data` as + /// arguments. This `record` function will call `op` to generate + /// the `Entry` (which may point to other encoded information) + /// and will then record the `Lazy` for use in the index. + // FIXME(eddyb) remove this. + pub fn record(&mut self, + id: DefId, + op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>, + data: DATA) + { + assert!(id.is_local()); + + let entry = op(self, data); + let entry = self.lazy(entry); + self.entries_index.record(id, entry); + } + fn encode_info_for_items(&mut self) { let krate = self.tcx.hir().krate(); let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public }; - self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis); + self.record(DefId::local(CRATE_DEF_INDEX), + EncodeContext::encode_info_for_mod, + (hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis)); krate.visit_all_item_likes(&mut self.as_deep_visitor()); for macro_def in &krate.exported_macros { self.visit_macro_def(macro_def); @@ -395,9 +368,9 @@ impl<'tcx> EncodeContext<'tcx> { let mut adapted = (**source_file).clone(); adapted.name = Path::new(&working_dir).join(name).into(); adapted.name_hash = { - let mut hasher: StableHasher = StableHasher::new(); + let mut hasher: StableHasher = StableHasher::new(); adapted.name.hash(&mut hasher); - hasher.finish::() + hasher.finish() }; Lrc::new(adapted) }, @@ -501,29 +474,8 @@ impl<'tcx> EncodeContext<'tcx> { i = self.position(); - let per_def = LazyPerDefTables { - kind: self.per_def.kind.encode(&mut self.opaque), - visibility: self.per_def.visibility.encode(&mut self.opaque), - span: self.per_def.span.encode(&mut self.opaque), - attributes: self.per_def.attributes.encode(&mut self.opaque), - children: self.per_def.children.encode(&mut self.opaque), - stability: self.per_def.stability.encode(&mut self.opaque), - deprecation: self.per_def.deprecation.encode(&mut self.opaque), - - ty: self.per_def.ty.encode(&mut self.opaque), - fn_sig: self.per_def.fn_sig.encode(&mut self.opaque), - impl_trait_ref: self.per_def.impl_trait_ref.encode(&mut self.opaque), - inherent_impls: self.per_def.inherent_impls.encode(&mut self.opaque), - variances: self.per_def.variances.encode(&mut self.opaque), - generics: self.per_def.generics.encode(&mut self.opaque), - predicates: self.per_def.predicates.encode(&mut self.opaque), - predicates_defined_on: self.per_def.predicates_defined_on.encode(&mut self.opaque), - super_predicates: self.per_def.super_predicates.encode(&mut self.opaque), - - mir: self.per_def.mir.encode(&mut self.opaque), - promoted_mir: self.per_def.promoted_mir.encode(&mut self.opaque), - }; - let per_def_bytes = self.position() - i; + 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(); @@ -582,7 +534,7 @@ impl<'tcx> EncodeContext<'tcx> { impls, exported_symbols, interpret_alloc_index, - per_def, + entries_index, }); let total_bytes = self.position(); @@ -607,7 +559,7 @@ impl<'tcx> EncodeContext<'tcx> { println!(" def-path table bytes: {}", def_path_table_bytes); println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes); println!(" item bytes: {}", item_bytes); - println!(" per-def table bytes: {}", per_def_bytes); + println!(" entries index bytes: {}", entries_index_bytes); println!(" zero bytes: {}", zero_bytes); println!(" total bytes: {}", total_bytes); } @@ -617,21 +569,23 @@ impl<'tcx> EncodeContext<'tcx> { } impl EncodeContext<'tcx> { - fn encode_variances_of(&mut self, def_id: DefId) { + fn encode_variances_of(&mut self, def_id: DefId) -> Lazy<[ty::Variance]> { debug!("EncodeContext::encode_variances_of({:?})", def_id); - record!(self.per_def.variances[def_id] <- &self.tcx.variances_of(def_id)[..]); + let tcx = self.tcx; + self.lazy(&tcx.variances_of(def_id)[..]) } - fn encode_item_type(&mut self, def_id: DefId) { - debug!("EncodeContext::encode_item_type({:?})", def_id); - record!(self.per_def.ty[def_id] <- self.tcx.type_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) } fn encode_enum_variant_info( &mut self, - enum_did: DefId, - index: VariantIdx, - ) { + (enum_did, index): (DefId, VariantIdx), + ) -> Entry<'tcx> { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; @@ -641,54 +595,65 @@ impl EncodeContext<'tcx> { let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, + // FIXME(eddyb) deduplicate these with `encode_enum_variant_ctor`. ctor: variant.ctor_def_id.map(|did| did.index), + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + variant.ctor_def_id.map(|ctor_def_id| self.lazy(&tcx.fn_sig(ctor_def_id))) + } else { + None + }, }; let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap(); let enum_vis = &tcx.hir().expect_item(enum_id).vis; - record!(self.per_def.kind[def_id] <- EntryKind::Variant(self.lazy(data))); - record!(self.per_def.visibility[def_id] <- - ty::Visibility::from_hir(enum_vis, enum_id, self.tcx)); - record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); - record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]); - record!(self.per_def.children[def_id] <- variant.fields.iter().map(|f| { - assert!(f.did.is_local()); - f.did.index - })); - self.encode_stability(def_id); - self.encode_deprecation(def_id); - self.encode_item_type(def_id); - if variant.ctor_kind == CtorKind::Fn { - // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`. - if let Some(ctor_def_id) = variant.ctor_def_id { - record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(ctor_def_id)); - } - // FIXME(eddyb) is this ever used? - self.encode_variances_of(def_id); + 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)), + attributes: self.encode_attributes(&tcx.get_attrs(def_id)), + children: self.lazy(variant.fields.iter().map(|f| { + assert!(f.did.is_local()); + f.did.index + })), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: Lazy::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + 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), } - self.encode_generics(def_id); - self.encode_predicates(def_id); - self.encode_optimized_mir(def_id); - self.encode_promoted_mir(def_id); } fn encode_enum_variant_ctor( &mut self, - enum_did: DefId, - index: VariantIdx, - ) { + (enum_did, index): (DefId, VariantIdx), + ) -> Entry<'tcx> { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; let def_id = variant.ctor_def_id.unwrap(); debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id); - // FIXME(eddyb) encode only the `CtorKind` for constructors. let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: Some(def_id.index), + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + Some(self.lazy(tcx.fn_sig(def_id))) + } else { + None + } }; // Variant constructors have the same visibility as the parent enums, unless marked as @@ -700,29 +665,35 @@ impl EncodeContext<'tcx> { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } - record!(self.per_def.kind[def_id] <- EntryKind::Variant(self.lazy(data))); - record!(self.per_def.visibility[def_id] <- ctor_vis); - record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); - self.encode_stability(def_id); - self.encode_deprecation(def_id); - self.encode_item_type(def_id); - if variant.ctor_kind == CtorKind::Fn { - record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); - self.encode_variances_of(def_id); + Entry { + 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: Lazy::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + 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), } - self.encode_generics(def_id); - self.encode_predicates(def_id); - self.encode_optimized_mir(def_id); - self.encode_promoted_mir(def_id); } fn encode_info_for_mod( &mut self, - id: hir::HirId, - md: &hir::Mod, - attrs: &[ast::Attribute], - vis: &hir::Visibility, - ) { + (id, md, attrs, vis): (hir::HirId, &hir::Mod, &[ast::Attribute], &hir::Visibility), + ) -> Entry<'tcx> { let tcx = self.tcx; let def_id = tcx.hir().local_def_id(id); debug!("EncodeContext::encode_info_for_mod({:?})", def_id); @@ -734,23 +705,33 @@ impl EncodeContext<'tcx> { }, }; - record!(self.per_def.kind[def_id] <- EntryKind::Mod(self.lazy(data))); - record!(self.per_def.visibility[def_id] <- ty::Visibility::from_hir(vis, id, self.tcx)); - record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); - record!(self.per_def.attributes[def_id] <- attrs); - record!(self.per_def.children[def_id] <- md.item_ids.iter().map(|item_id| { - tcx.hir().local_def_id(item_id.id).index - })); - self.encode_stability(def_id); - self.encode_deprecation(def_id); + 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)), + attributes: self.encode_attributes(attrs), + 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: Lazy::empty(), + variances: Lazy::empty(), + generics: None, + predicates: None, + predicates_defined_on: None, + + mir: None, + promoted_mir: None, + } } fn encode_field( &mut self, - adt_def_id: DefId, - variant_index: VariantIdx, - field_index: usize, - ) { + (adt_def_id, variant_index, field_index): (DefId, VariantIdx, usize), + ) -> Entry<'tcx> { let tcx = self.tcx; let variant = &tcx.adt_def(adt_def_id).variants[variant_index]; let field = &variant.fields[field_index]; @@ -761,18 +742,28 @@ impl EncodeContext<'tcx> { let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap(); let variant_data = tcx.hir().expect_variant_data(variant_id); - record!(self.per_def.kind[def_id] <- EntryKind::Field); - record!(self.per_def.visibility[def_id] <- field.vis); - record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); - record!(self.per_def.attributes[def_id] <- &variant_data.fields()[field_index].attrs); - self.encode_stability(def_id); - self.encode_deprecation(def_id); - self.encode_item_type(def_id); - self.encode_generics(def_id); - self.encode_predicates(def_id); + Entry { + kind: EntryKind::Field, + visibility: self.lazy(field.vis), + span: self.lazy(tcx.def_span(def_id)), + attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs), + 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: 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, + } } - fn encode_struct_ctor(&mut self, adt_def_id: DefId, def_id: DefId) { + fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> { debug!("EncodeContext::encode_struct_ctor({:?})", def_id); let tcx = self.tcx; let adt_def = tcx.adt_def(adt_def_id); @@ -782,6 +773,11 @@ impl EncodeContext<'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: Some(def_id.index), + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + Some(self.lazy(tcx.fn_sig(def_id))) + } else { + None + } }; let struct_id = tcx.hir().as_local_hir_id(adt_def_id).unwrap(); @@ -801,44 +797,52 @@ impl EncodeContext<'tcx> { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } - record!(self.per_def.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr)); - record!(self.per_def.visibility[def_id] <- ctor_vis); - record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); - self.encode_stability(def_id); - self.encode_deprecation(def_id); - self.encode_item_type(def_id); - if variant.ctor_kind == CtorKind::Fn { - record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); - self.encode_variances_of(def_id); + 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: 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: Lazy::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + 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), } - self.encode_generics(def_id); - self.encode_predicates(def_id); - self.encode_optimized_mir(def_id); - self.encode_promoted_mir(def_id); } - fn encode_generics(&mut self, def_id: DefId) { + fn encode_generics(&mut self, def_id: DefId) -> Lazy { debug!("EncodeContext::encode_generics({:?})", def_id); - record!(self.per_def.generics[def_id] <- self.tcx.generics_of(def_id)); + let tcx = self.tcx; + self.lazy(tcx.generics_of(def_id)) } - fn encode_predicates(&mut self, def_id: DefId) { + fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { debug!("EncodeContext::encode_predicates({:?})", def_id); - record!(self.per_def.predicates[def_id] <- self.tcx.predicates_of(def_id)); + let tcx = self.tcx; + self.lazy(&*tcx.predicates_of(def_id)) } - fn encode_predicates_defined_on(&mut self, def_id: DefId) { + fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy> { debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id); - record!(self.per_def.predicates_defined_on[def_id] <- - self.tcx.predicates_defined_on(def_id)) - } - - fn encode_super_predicates(&mut self, def_id: DefId) { - debug!("EncodeContext::encode_super_predicates({:?})", def_id); - record!(self.per_def.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id)); + let tcx = self.tcx; + self.lazy(&*tcx.predicates_defined_on(def_id)) } - fn encode_info_for_trait_item(&mut self, def_id: DefId) { + fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; @@ -855,16 +859,23 @@ impl EncodeContext<'tcx> { span_bug!(ast_item.span, "traits cannot have final items"), }; - record!(self.per_def.kind[def_id] <- match trait_item.kind { + let kind = match trait_item.kind { ty::AssocKind::Const => { + let const_qualif = + if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.kind { + self.const_qualif(0, body) + } else { + ConstQualif { mir: 0, ast_promotable: false } + }; + let rendered = hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item)); let rendered_const = self.lazy(RenderedConst(rendered)); - EntryKind::AssocConst(container, ConstQualif { mir: 0 }, rendered_const) + EntryKind::AssocConst(container, const_qualif, rendered_const) } ty::AssocKind::Method => { - let fn_data = if let hir::TraitItemKind::Method(m_sig, m) = &ast_item.kind { + let fn_data = if let hir::TraitItemKind::Method(method_sig, m) = &ast_item.kind { let param_names = match *m { hir::TraitMethod::Required(ref names) => { self.encode_fn_param_names(names) @@ -874,9 +885,10 @@ impl EncodeContext<'tcx> { } }; FnData { - asyncness: m_sig.header.asyncness, + asyncness: method_sig.header.asyncness, constness: hir::Constness::NotConst, param_names, + sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() @@ -889,32 +901,44 @@ impl EncodeContext<'tcx> { } ty::AssocKind::Type => EntryKind::AssocType(container), ty::AssocKind::OpaqueTy => span_bug!(ast_item.span, "opaque type in trait"), - }); - record!(self.per_def.visibility[def_id] <- trait_item.vis); - record!(self.per_def.span[def_id] <- ast_item.span); - record!(self.per_def.attributes[def_id] <- &ast_item.attrs); - self.encode_stability(def_id); - self.encode_deprecation(def_id); - match trait_item.kind { - ty::AssocKind::Const | - ty::AssocKind::Method => { - self.encode_item_type(def_id); - } - ty::AssocKind::Type => { - if trait_item.defaultness.has_value() { - self.encode_item_type(def_id); + }; + + Entry { + kind, + visibility: self.lazy(trait_item.vis), + span: self.lazy(ast_item.span), + attributes: self.encode_attributes(&ast_item.attrs), + children: Lazy::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: match trait_item.kind { + ty::AssocKind::Const | + ty::AssocKind::Method => { + Some(self.encode_item_type(def_id)) } - } - ty::AssocKind::OpaqueTy => unreachable!(), - } - if trait_item.kind == ty::AssocKind::Method { - record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); - self.encode_variances_of(def_id); + ty::AssocKind::Type => { + if trait_item.defaultness.has_value() { + Some(self.encode_item_type(def_id)) + } else { + None + } + } + ty::AssocKind::OpaqueTy => unreachable!(), + }, + inherent_impls: Lazy::empty(), + variances: if trait_item.kind == ty::AssocKind::Method { + self.encode_variances_of(def_id) + } else { + 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), } - self.encode_generics(def_id); - self.encode_predicates(def_id); - self.encode_optimized_mir(def_id); - self.encode_promoted_mir(def_id); } fn metadata_output_only(&self) -> bool { @@ -922,7 +946,14 @@ impl EncodeContext<'tcx> { !self.tcx.sess.opts.output_types.should_codegen() } - fn encode_info_for_impl_item(&mut self, def_id: DefId) { + fn const_qualif(&self, mir: u8, body_id: hir::BodyId) -> ConstQualif { + let body_owner_def_id = self.tcx.hir().body_owner_def_id(body_id); + let ast_promotable = self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id); + + ConstQualif { mir, ast_promotable } + } + + fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; @@ -937,13 +968,13 @@ impl EncodeContext<'tcx> { span_bug!(ast_item.span, "impl items always have values (currently)"), }; - record!(self.per_def.kind[def_id] <- match impl_item.kind { + let kind = match impl_item.kind { ty::AssocKind::Const => { if let hir::ImplItemKind::Const(_, body_id) = ast_item.kind { let mir = self.tcx.at(ast_item.span).mir_const_qualif(def_id).0; EntryKind::AssocConst(container, - ConstQualif { mir }, + self.const_qualif(mir, body_id), self.encode_rendered_const_for_body(body_id)) } else { bug!() @@ -955,6 +986,7 @@ impl EncodeContext<'tcx> { asyncness: sig.header.asyncness, constness: sig.header.constness, param_names: self.encode_fn_param_names_for_body(body), + sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() @@ -967,19 +999,8 @@ impl EncodeContext<'tcx> { } ty::AssocKind::OpaqueTy => EntryKind::AssocOpaqueTy(container), ty::AssocKind::Type => EntryKind::AssocType(container) - }); - record!(self.per_def.visibility[def_id] <- impl_item.vis); - record!(self.per_def.span[def_id] <- ast_item.span); - record!(self.per_def.attributes[def_id] <- &ast_item.attrs); - self.encode_stability(def_id); - self.encode_deprecation(def_id); - self.encode_item_type(def_id); - if impl_item.kind == ty::AssocKind::Method { - record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); - self.encode_variances_of(def_id); - } - self.encode_generics(def_id); - self.encode_predicates(def_id); + }; + let mir = match ast_item.kind { hir::ImplItemKind::Const(..) => true, hir::ImplItemKind::Method(ref sig, _) => { @@ -994,9 +1015,29 @@ impl EncodeContext<'tcx> { hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => false, }; - if mir { - self.encode_optimized_mir(def_id); - self.encode_promoted_mir(def_id); + + Entry { + kind, + visibility: self.lazy(impl_item.vis), + span: self.lazy(ast_item.span), + attributes: self.encode_attributes(&ast_item.attrs), + 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: Lazy::empty(), + variances: if impl_item.kind == ty::AssocKind::Method { + self.encode_variances_of(def_id) + } else { + 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 }, } } @@ -1017,44 +1058,51 @@ impl EncodeContext<'tcx> { self.lazy(param_names.iter().map(|ident| ident.name)) } - fn encode_optimized_mir(&mut self, def_id: DefId) { + 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) { - record!(self.per_def.mir[def_id] <- self.tcx.optimized_mir(def_id)); + let mir = self.tcx.optimized_mir(def_id); + Some(self.lazy(mir)) + } else { + None } } - fn encode_promoted_mir(&mut self, def_id: DefId) { + 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) { - record!(self.per_def.promoted_mir[def_id] <- self.tcx.promoted_mir(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) { + 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() { - record!(self.per_def.inherent_impls[def_id] <- implementations.iter().map(|&def_id| { + if implementations.is_empty() { + Lazy::empty() + } else { + self.lazy(implementations.iter().map(|&def_id| { assert!(def_id.is_local()); def_id.index - })); + })) } } - fn encode_stability(&mut self, def_id: DefId) { + fn encode_stability(&mut self, def_id: DefId) -> Option> { debug!("EncodeContext::encode_stability({:?})", def_id); - if let Some(stab) = self.tcx.lookup_stability(def_id) { - record!(self.per_def.stability[def_id] <- stab) - } + self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab)) } - fn encode_deprecation(&mut self, def_id: DefId) { + fn encode_deprecation(&mut self, def_id: DefId) -> Option> { debug!("EncodeContext::encode_deprecation({:?})", def_id); - if let Some(depr) = self.tcx.lookup_deprecation(def_id) { - record!(self.per_def.deprecation[def_id] <- 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 { @@ -1064,18 +1112,18 @@ impl EncodeContext<'tcx> { self.lazy(rendered_const) } - fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) { + fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> { let tcx = self.tcx; debug!("EncodeContext::encode_info_for_item({:?})", def_id); - record!(self.per_def.kind[def_id] <- match item.kind { + let kind = match item.kind { hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic, hir::ItemKind::Static(_, hir::MutImmutable, _) => EntryKind::ImmStatic, hir::ItemKind::Const(_, body_id) => { - let mir = self.tcx.at(item.span).mir_const_qualif(def_id).0; + let mir = tcx.at(item.span).mir_const_qualif(def_id).0; EntryKind::Const( - ConstQualif { mir }, + self.const_qualif(mir, body_id), self.encode_rendered_const_for_body(body_id) ) } @@ -1084,51 +1132,54 @@ impl EncodeContext<'tcx> { asyncness: header.asyncness, constness: header.constness, param_names: self.encode_fn_param_names_for_body(body), + sig: self.lazy(tcx.fn_sig(def_id)), }; EntryKind::Fn(self.lazy(data)) } hir::ItemKind::Mod(ref m) => { - return self.encode_info_for_mod(item.hir_id, m, &item.attrs, &item.vis); + return self.encode_info_for_mod((item.hir_id, m, &item.attrs, &item.vis)); } hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod, hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, hir::ItemKind::TyAlias(..) => EntryKind::Type, hir::ItemKind::OpaqueTy(..) => EntryKind::OpaqueTy, - hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr), + hir::ItemKind::Enum(..) => EntryKind::Enum(get_repr_options(tcx, def_id)), hir::ItemKind::Struct(ref struct_def, _) => { - let adt_def = self.tcx.adt_def(def_id); - let variant = adt_def.non_enum_variant(); + let variant = tcx.adt_def(def_id).non_enum_variant(); // Encode def_ids for each field and method // for methods, write all the stuff get_trait_method // needs to know - let ctor = struct_def.ctor_hir_id().map(|ctor_hir_id| { - self.tcx.hir().local_def_id(ctor_hir_id).index - }); + let ctor = struct_def.ctor_hir_id() + .map(|ctor_hir_id| tcx.hir().local_def_id(ctor_hir_id).index); + + let repr_options = get_repr_options(tcx, def_id); EntryKind::Struct(self.lazy(VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor, - }), adt_def.repr) + ctor_sig: None, + }), repr_options) } hir::ItemKind::Union(..) => { - let adt_def = self.tcx.adt_def(def_id); - let variant = adt_def.non_enum_variant(); + let variant = tcx.adt_def(def_id).non_enum_variant(); + let repr_options = get_repr_options(tcx, def_id); EntryKind::Union(self.lazy(VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: None, - }), adt_def.repr) + ctor_sig: None, + }), repr_options) } hir::ItemKind::Impl(_, _, defaultness, ..) => { - let trait_ref = self.tcx.impl_trait_ref(def_id); - let polarity = self.tcx.impl_polarity(def_id); + let trait_ref = tcx.impl_trait_ref(def_id); + let polarity = tcx.impl_polarity(def_id); let parent = if let Some(trait_ref) = trait_ref { - let trait_def = self.tcx.trait_def(trait_ref.def_id); - trait_def.ancestors(self.tcx, def_id).nth(1).and_then(|node| { + let trait_def = tcx.trait_def(trait_ref.def_id); + trait_def.ancestors(tcx, def_id).nth(1).and_then(|node| { match node { specialization_graph::Node::Impl(parent) => Some(parent), _ => None, @@ -1142,8 +1193,8 @@ impl EncodeContext<'tcx> { // "unsized info", else just store None let coerce_unsized_info = trait_ref.and_then(|t| { - if Some(t.def_id) == self.tcx.lang_items().coerce_unsized_trait() { - Some(self.tcx.at(item.span).coerce_unsized_info(def_id)) + if Some(t.def_id) == tcx.lang_items().coerce_unsized_trait() { + Some(tcx.at(item.span).coerce_unsized_info(def_id)) } else { None } @@ -1154,128 +1205,33 @@ impl EncodeContext<'tcx> { defaultness, parent_impl: parent, coerce_unsized_info, + trait_ref: trait_ref.map(|trait_ref| self.lazy(trait_ref)), }; EntryKind::Impl(self.lazy(data)) } hir::ItemKind::Trait(..) => { - let trait_def = self.tcx.trait_def(def_id); + let trait_def = tcx.trait_def(def_id); let data = TraitData { unsafety: trait_def.unsafety, paren_sugar: trait_def.paren_sugar, - has_auto_impl: self.tcx.trait_is_auto(def_id), + 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)), }; EntryKind::Trait(self.lazy(data)) } - hir::ItemKind::TraitAlias(..) => EntryKind::TraitAlias, - hir::ItemKind::ExternCrate(_) | - hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), - }); - record!(self.per_def.visibility[def_id] <- - ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)); - record!(self.per_def.span[def_id] <- item.span); - record!(self.per_def.attributes[def_id] <- &item.attrs); - // FIXME(eddyb) there should be a nicer way to do this. - match item.kind { - hir::ItemKind::ForeignMod(ref fm) => record!(self.per_def.children[def_id] <- - fm.items - .iter() - .map(|foreign_item| tcx.hir().local_def_id( - foreign_item.hir_id).index) - ), - hir::ItemKind::Enum(..) => record!(self.per_def.children[def_id] <- - self.tcx.adt_def(def_id).variants.iter().map(|v| { - assert!(v.def_id.is_local()); - v.def_id.index - }) - ), - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) => record!(self.per_def.children[def_id] <- - self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| { - assert!(f.did.is_local()); - f.did.index - }) - ), - hir::ItemKind::Impl(..) | - hir::ItemKind::Trait(..) => { - let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id); - record!(self.per_def.children[def_id] <- - associated_item_def_ids.iter().map(|&def_id| { - assert!(def_id.is_local()); - def_id.index - }) - ); - } - _ => {} - } - self.encode_stability(def_id); - self.encode_deprecation(def_id); - match item.kind { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::TyAlias(..) | - hir::ItemKind::OpaqueTy(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) => self.encode_item_type(def_id), - _ => {} - } - if let hir::ItemKind::Fn(..) = item.kind { - record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); - } - if let hir::ItemKind::Impl(..) = item.kind { - if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) { - record!(self.per_def.impl_trait_ref[def_id] <- trait_ref); - } - } - self.encode_inherent_implementations(def_id); - match item.kind { - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => {} - } - match item.kind { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::TyAlias(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) | - hir::ItemKind::OpaqueTy(..) | - hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => { - self.encode_generics(def_id); - self.encode_predicates(def_id); - } - _ => {} - } - // The only time that `predicates_defined_on` is used (on - // an external item) is for traits, during chalk lowering, - // so only encode it in that case as an efficiency - // hack. (No reason not to expand it in the future if - // necessary.) - match item.kind { - hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => { - self.encode_predicates_defined_on(def_id); - } - _ => {} // not *wrong* for other kinds of items, but not needed - } - match item.kind { - hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => { - self.encode_super_predicates(def_id); + let data = TraitAliasData { + super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), + }; + + EntryKind::TraitAlias(self.lazy(data)) } - _ => {} - } + hir::ItemKind::ExternCrate(_) | + hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), + }; let mir = match item.kind { hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true, @@ -1290,50 +1246,188 @@ impl EncodeContext<'tcx> { } _ => false, }; - if mir { - self.encode_optimized_mir(def_id); - self.encode_promoted_mir(def_id); + + Entry { + kind, + 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.kind { + hir::ItemKind::ForeignMod(ref fm) => { + 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(def.variants.iter().map(|v| { + assert!(v.def_id.is_local()); + v.def_id.index + })) + } + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) => { + let def = self.tcx.adt_def(def_id); + 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(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { + assert!(def_id.is_local()); + def_id.index + })) + } + _ => Lazy::empty(), + }, + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: match item.kind { + hir::ItemKind::Static(..) | + hir::ItemKind::Const(..) | + hir::ItemKind::Fn(..) | + hir::ItemKind::TyAlias(..) | + hir::ItemKind::OpaqueTy(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Impl(..) => Some(self.encode_item_type(def_id)), + _ => None, + }, + inherent_impls: self.encode_inherent_implementations(def_id), + variances: match item.kind { + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), + _ => Lazy::empty(), + }, + generics: match item.kind { + hir::ItemKind::Static(..) | + hir::ItemKind::Const(..) | + hir::ItemKind::Fn(..) | + hir::ItemKind::TyAlias(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Impl(..) | + hir::ItemKind::OpaqueTy(..) | + hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)), + hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)), + _ => None, + }, + predicates: match item.kind { + hir::ItemKind::Static(..) | + hir::ItemKind::Const(..) | + hir::ItemKind::Fn(..) | + hir::ItemKind::TyAlias(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Impl(..) | + hir::ItemKind::OpaqueTy(..) | + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)), + _ => None, + }, + + // The only time that `predicates_defined_on` is used (on + // an external item) is for traits, during chalk lowering, + // so only encode it in that case as an efficiency + // hack. (No reason not to expand it in the future if + // necessary.) + predicates_defined_on: match item.kind { + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates_defined_on(def_id)), + _ => None, // not *wrong* for other kinds of items, but not needed + }, + + mir: if mir { self.encode_optimized_mir(def_id) } else { None }, + promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, } } /// Serialize the text of exported macros - fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) { + fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> { use syntax::print::pprust; let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); - record!(self.per_def.kind[def_id] <- EntryKind::MacroDef(self.lazy(MacroDef { - body: pprust::tts_to_string(macro_def.body.clone()), - legacy: macro_def.legacy, - }))); - record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); - record!(self.per_def.span[def_id] <- macro_def.span); - record!(self.per_def.attributes[def_id] <- ¯o_def.attrs); - self.encode_stability(def_id); - self.encode_deprecation(def_id); + Entry { + 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(macro_def.span), + attributes: self.encode_attributes(¯o_def.attrs), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + children: Lazy::empty(), + ty: None, + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), + generics: None, + predicates: None, + predicates_defined_on: None, + mir: None, + promoted_mir: None, + } } fn encode_info_for_generic_param( &mut self, def_id: DefId, - kind: EntryKind<'tcx>, + entry_kind: EntryKind<'tcx>, encode_type: bool, - ) { - record!(self.per_def.kind[def_id] <- kind); - record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); - record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); - if encode_type { - self.encode_item_type(def_id); + ) -> Entry<'tcx> { + let tcx = self.tcx; + Entry { + kind: entry_kind, + 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: Lazy::empty(), + variances: Lazy::empty(), + generics: None, + predicates: None, + predicates_defined_on: None, + + mir: None, + promoted_mir: None, } } - fn encode_info_for_closure(&mut self, def_id: DefId) { + fn encode_info_for_ty_param( + &mut self, + (def_id, encode_type): (DefId, bool), + ) -> Entry<'tcx> { + debug!("EncodeContext::encode_info_for_ty_param({:?})", def_id); + self.encode_info_for_generic_param(def_id, EntryKind::TypeParam, encode_type) + } + + fn encode_info_for_const_param( + &mut self, + def_id: DefId, + ) -> Entry<'tcx> { + debug!("EncodeContext::encode_info_for_const_param({:?})", def_id); + self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true) + } + + fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> { debug!("EncodeContext::encode_info_for_closure({:?})", def_id); + let tcx = self.tcx; - // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic, - // including on the signature, which is inferred in `typeck_tables_of. + let tables = self.tcx.typeck_tables_of(def_id); let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); - let ty = self.tcx.typeck_tables_of(def_id).node_type(hir_id); - - record!(self.per_def.kind[def_id] <- match ty.kind { + let kind = match tables.node_type(hir_id).kind { ty::Generator(def_id, ..) => { let layout = self.tcx.generator_layout(def_id); let data = GeneratorData { @@ -1342,37 +1436,67 @@ impl EncodeContext<'tcx> { EntryKind::Generator(self.lazy(data)) } - ty::Closure(..) => EntryKind::Closure, + 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)) + } + + _ => bug!("closure that is neither generator nor closure") + }; - _ => bug!("closure that is neither generator nor closure"), - }); - record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); - record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); - record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]); - self.encode_item_type(def_id); - if let ty::Closure(def_id, substs) = ty.kind { - record!(self.per_def.fn_sig[def_id] <- substs.as_closure().sig(def_id, self.tcx)); + Entry { + kind, + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), + attributes: self.encode_attributes(&tcx.get_attrs(def_id)), + children: Lazy::empty(), + stability: None, + deprecation: None, + + ty: Some(self.encode_item_type(def_id)), + 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), } - self.encode_generics(def_id); - self.encode_optimized_mir(def_id); - self.encode_promoted_mir(def_id); } - fn encode_info_for_anon_const(&mut self, def_id: DefId) { + fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> { debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id); - let id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); - let body_id = self.tcx.hir().body_owned_by(id); + let tcx = self.tcx; + let id = tcx.hir().as_local_hir_id(def_id).unwrap(); + let body_id = tcx.hir().body_owned_by(id); let const_data = self.encode_rendered_const_for_body(body_id); - let mir = self.tcx.mir_const_qualif(def_id).0; + let mir = tcx.mir_const_qualif(def_id).0; + + 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: Lazy::empty(), + children: Lazy::empty(), + stability: None, + deprecation: None, + + ty: Some(self.encode_item_type(def_id)), + 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), + } + } - record!(self.per_def.kind[def_id] <- EntryKind::Const(ConstQualif { mir }, const_data)); - record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); - record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); - self.encode_item_type(def_id); - self.encode_generics(def_id); - self.encode_predicates(def_id); - self.encode_optimized_mir(def_id); - self.encode_promoted_mir(def_id); + fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> Lazy<[ast::Attribute]> { + self.lazy(attrs) } fn encode_native_libraries(&mut self) -> Lazy<[NativeLibrary]> { @@ -1546,45 +1670,53 @@ impl EncodeContext<'tcx> { Lazy::empty() } - fn encode_info_for_foreign_item( - &mut self, - def_id: DefId, - nitem: &hir::ForeignItem, - ) { + fn encode_info_for_foreign_item(&mut self, + (def_id, nitem): (DefId, &hir::ForeignItem)) + -> Entry<'tcx> { let tcx = self.tcx; debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id); - record!(self.per_def.kind[def_id] <- match nitem.kind { + let kind = match nitem.kind { hir::ForeignItemKind::Fn(_, ref names, _) => { let data = FnData { asyncness: hir::IsAsync::NotAsync, constness: hir::Constness::NotConst, param_names: self.encode_fn_param_names(names), + sig: self.lazy(tcx.fn_sig(def_id)), }; EntryKind::ForeignFn(self.lazy(data)) } hir::ForeignItemKind::Static(_, hir::MutMutable) => EntryKind::ForeignMutStatic, hir::ForeignItemKind::Static(_, hir::MutImmutable) => EntryKind::ForeignImmStatic, hir::ForeignItemKind::Type => EntryKind::ForeignType, - }); - record!(self.per_def.visibility[def_id] <- - ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, self.tcx)); - record!(self.per_def.span[def_id] <- nitem.span); - record!(self.per_def.attributes[def_id] <- &nitem.attrs); - self.encode_stability(def_id); - self.encode_deprecation(def_id); - self.encode_item_type(def_id); - if let hir::ForeignItemKind::Fn(..) = nitem.kind { - record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); - self.encode_variances_of(def_id); + }; + + Entry { + kind, + 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: Lazy::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: Lazy::empty(), + variances: match nitem.kind { + hir::ForeignItemKind::Fn(..) => self.encode_variances_of(def_id), + _ => 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, } - self.encode_generics(def_id); - self.encode_predicates(def_id); } } -// FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR. impl Visitor<'tcx> for EncodeContext<'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::OnlyBodies(&self.tcx.hir()) @@ -1593,32 +1725,45 @@ impl Visitor<'tcx> for EncodeContext<'tcx> { intravisit::walk_expr(self, ex); self.encode_info_for_expr(ex); } - fn visit_anon_const(&mut self, c: &'tcx AnonConst) { - intravisit::walk_anon_const(self, c); - let def_id = self.tcx.hir().local_def_id(c.hir_id); - self.encode_info_for_anon_const(def_id); - } fn visit_item(&mut self, item: &'tcx hir::Item) { intravisit::walk_item(self, item); let def_id = self.tcx.hir().local_def_id(item.hir_id); match item.kind { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these - _ => self.encode_info_for_item(def_id, item), + _ => self.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)), } self.encode_addl_info_for_item(item); } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) { intravisit::walk_foreign_item(self, ni); let def_id = self.tcx.hir().local_def_id(ni.hir_id); - self.encode_info_for_foreign_item(def_id, ni); + self.record(def_id, + EncodeContext::encode_info_for_foreign_item, + (def_id, ni)); + } + fn visit_variant(&mut self, + v: &'tcx hir::Variant, + g: &'tcx hir::Generics, + id: hir::HirId) { + intravisit::walk_variant(self, v, g, id); + + 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); + } } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { intravisit::walk_generics(self, generics); self.encode_info_for_generics(generics); } + fn visit_ty(&mut self, ty: &'tcx hir::Ty) { + intravisit::walk_ty(self, ty); + self.encode_info_for_ty(ty); + } fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { - self.encode_info_for_macro_def(macro_def); + let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); + self.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def); } } @@ -1626,10 +1771,10 @@ impl EncodeContext<'tcx> { fn encode_fields(&mut self, adt_def_id: DefId) { let def = self.tcx.adt_def(adt_def_id); for (variant_index, variant) in def.variants.iter_enumerated() { - for (field_index, _field) in variant.fields.iter().enumerate() { - // FIXME(eddyb) `adt_def_id` is leftover from incremental isolation, - // pass `def`, `variant` or `field` instead. - self.encode_field(adt_def_id, variant_index, field_index); + for (field_index, field) in variant.fields.iter().enumerate() { + self.record(field.did, + EncodeContext::encode_field, + (adt_def_id, variant_index, field_index)); } } } @@ -1640,24 +1785,34 @@ impl EncodeContext<'tcx> { match param.kind { GenericParamKind::Lifetime { .. } => continue, GenericParamKind::Type { ref default, .. } => { - self.encode_info_for_generic_param( + self.record( def_id, - EntryKind::TypeParam, - default.is_some(), + EncodeContext::encode_info_for_ty_param, + (def_id, default.is_some()), ); } GenericParamKind::Const { .. } => { - self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true); + self.record(def_id, EncodeContext::encode_info_for_const_param, def_id); } } } } + fn encode_info_for_ty(&mut self, ty: &hir::Ty) { + match ty.kind { + hir::TyKind::Array(_, ref length) => { + let def_id = self.tcx.hir().local_def_id(length.hir_id); + self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); + } + _ => {} + } + } + fn encode_info_for_expr(&mut self, expr: &hir::Expr) { match expr.kind { hir::ExprKind::Closure(..) => { let def_id = self.tcx.hir().local_def_id(expr.hir_id); - self.encode_info_for_closure(def_id); + self.record(def_id, EncodeContext::encode_info_for_closure, def_id); } _ => {} } @@ -1688,14 +1843,14 @@ impl EncodeContext<'tcx> { let def = self.tcx.adt_def(def_id); for (i, variant) in def.variants.iter_enumerated() { - // FIXME(eddyb) `def_id` is leftover from incremental isolation, - // pass `def` or `variant` instead. - self.encode_enum_variant_info(def_id, i); - - // FIXME(eddyb) `def_id` is leftover from incremental isolation, - // pass `def`, `variant` or `ctor_def_id` instead. - if let Some(_ctor_def_id) = variant.ctor_def_id { - self.encode_enum_variant_ctor(def_id, i); + self.record(variant.def_id, + EncodeContext::encode_enum_variant_info, + (def_id, i)); + + if let Some(ctor_def_id) = variant.ctor_def_id { + self.record(ctor_def_id, + EncodeContext::encode_enum_variant_ctor, + (def_id, i)); } } } @@ -1705,7 +1860,9 @@ impl EncodeContext<'tcx> { // If the struct has a constructor, encode it. if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id); - self.encode_struct_ctor(def_id, ctor_def_id); + self.record(ctor_def_id, + EncodeContext::encode_struct_ctor, + (def_id, ctor_def_id)); } } hir::ItemKind::Union(..) => { @@ -1713,12 +1870,16 @@ impl EncodeContext<'tcx> { } hir::ItemKind::Impl(..) => { for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { - self.encode_info_for_impl_item(trait_item_def_id); + self.record(trait_item_def_id, + EncodeContext::encode_info_for_impl_item, + trait_item_def_id); } } hir::ItemKind::Trait(..) => { for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { - self.encode_info_for_trait_item(item_def_id); + self.record(item_def_id, + EncodeContext::encode_info_for_trait_item, + item_def_id); } } } @@ -1773,7 +1934,7 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { // will allow us to slice the metadata to the precise length that we just // generated regardless of trailing bytes that end up in it. -crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { +pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut encoder = opaque::Encoder::new(vec![]); encoder.emit_raw_bytes(METADATA_HEADER); @@ -1786,7 +1947,7 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut ecx = EncodeContext { opaque: encoder, tcx, - per_def: Default::default(), + entries_index: Index::new(tcx.hir().definitions().def_index_count()), lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), @@ -1806,7 +1967,7 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { // Encode the root position. let header = METADATA_HEADER.len(); - let pos = root.position.get(); + let pos = root.position; result[header + 0] = (pos >> 24) as u8; result[header + 1] = (pos >> 16) as u8; result[header + 2] = (pos >> 8) as u8; @@ -1814,3 +1975,11 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { EncodedMetadata { raw_data: result } } + +pub fn get_repr_options(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { + let ty = tcx.type_of(did); + match ty.kind { + ty::Adt(ref def, _) => return def.repr, + _ => bug!("{} is not an ADT", ty), + } +} diff --git a/src/librustc_metadata/foreign_modules.rs b/src/librustc_metadata/foreign_modules.rs index fa1402584eda5..8a4f6e6f17a51 100644 --- a/src/librustc_metadata/foreign_modules.rs +++ b/src/librustc_metadata/foreign_modules.rs @@ -3,7 +3,7 @@ use rustc::hir; use rustc::middle::cstore::ForeignModule; use rustc::ty::TyCtxt; -crate fn collect(tcx: TyCtxt<'_>) -> Vec { +pub fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { tcx, modules: Vec::new(), diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs new file mode 100644 index 0000000000000..6f248f22cf252 --- /dev/null +++ b/src/librustc_metadata/index.rs @@ -0,0 +1,141 @@ +use crate::schema::*; + +use rustc::hir::def_id::{DefId, DefIndex}; +use rustc_serialize::opaque::Encoder; +use std::marker::PhantomData; +use std::u32; +use log::debug; + +/// Helper trait, for encoding to, and decoding from, a fixed number of bytes. +pub trait FixedSizeEncoding { + const BYTE_LEN: usize; + + // FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead, + // once that starts being allowed by the compiler (i.e. lazy normalization). + fn from_bytes(b: &[u8]) -> Self; + fn write_to_bytes(self, b: &mut [u8]); + + // FIXME(eddyb) make these generic functions, or at least defaults here. + // (same problem as above, needs `[u8; Self::BYTE_LEN]`) + // For now, a macro (`fixed_size_encoding_byte_len_and_defaults`) is used. + fn read_from_bytes_at(b: &[u8], i: usize) -> Self; + fn write_to_bytes_at(self, b: &mut [u8], i: usize); +} + +// HACK(eddyb) this shouldn't be needed (see comments on the methods above). +macro_rules! fixed_size_encoding_byte_len_and_defaults { + ($byte_len:expr) => { + const BYTE_LEN: usize = $byte_len; + fn read_from_bytes_at(b: &[u8], i: usize) -> Self { + const BYTE_LEN: usize = $byte_len; + // HACK(eddyb) ideally this would be done with fully safe code, + // but slicing `[u8]` with `i * N..` is optimized worse, due to the + // possibility of `i * N` overflowing, than indexing `[[u8; N]]`. + let b = unsafe { + std::slice::from_raw_parts( + b.as_ptr() as *const [u8; BYTE_LEN], + b.len() / BYTE_LEN, + ) + }; + Self::from_bytes(&b[i]) + } + fn write_to_bytes_at(self, b: &mut [u8], i: usize) { + const BYTE_LEN: usize = $byte_len; + // HACK(eddyb) ideally this would be done with fully safe code, + // see similar comment in `read_from_bytes_at` for why it can't yet. + let b = unsafe { + std::slice::from_raw_parts_mut( + b.as_mut_ptr() as *mut [u8; BYTE_LEN], + b.len() / BYTE_LEN, + ) + }; + self.write_to_bytes(&mut b[i]); + } + } +} + +impl FixedSizeEncoding for u32 { + fixed_size_encoding_byte_len_and_defaults!(4); + + fn from_bytes(b: &[u8]) -> Self { + let mut bytes = [0; Self::BYTE_LEN]; + bytes.copy_from_slice(&b[..Self::BYTE_LEN]); + Self::from_le_bytes(bytes) + } + + fn write_to_bytes(self, b: &mut [u8]) { + b[..Self::BYTE_LEN].copy_from_slice(&self.to_le_bytes()); + } +} + +/// While we are generating the metadata, we also track the position +/// of each DefIndex. It is not required that all definitions appear +/// in the metadata, nor that they are serialized in order, and +/// therefore we first allocate the vector here and fill it with +/// `u32::MAX`. Whenever an index is visited, we fill in the +/// appropriate spot by calling `record_position`. We should never +/// visit the same index twice. +pub struct Index<'tcx> { + positions: Vec, + _marker: PhantomData<&'tcx ()>, +} + +impl Index<'tcx> { + pub fn new(max_index: usize) -> Self { + Index { + positions: vec![0xff; max_index * 4], + _marker: PhantomData, + } + } + + pub fn record(&mut self, def_id: DefId, entry: Lazy>) { + assert!(def_id.is_local()); + self.record_index(def_id.index, entry); + } + + pub fn record_index(&mut self, item: DefIndex, entry: Lazy>) { + assert!(entry.position < (u32::MAX as usize)); + let position = entry.position as u32; + let array_index = item.index(); + + let positions = &mut self.positions; + assert!(u32::read_from_bytes_at(positions, array_index) == u32::MAX, + "recorded position for item {:?} twice, first at {:?} and now at {:?}", + item, + u32::read_from_bytes_at(positions, array_index), + position); + + position.write_to_bytes_at(positions, array_index) + } + + 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); + Lazy::from_position_and_meta(pos as usize, self.positions.len() / 4 + 1) + } +} + +impl Lazy<[Index<'tcx>]> { + /// Given the metadata, extract out the offset of a particular + /// DefIndex (if any). + #[inline(never)] + pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option>> { + let bytes = &bytes[self.position..]; + debug!("Index::lookup: index={:?} len={:?}", + def_index, + self.meta); + + let position = u32::read_from_bytes_at(bytes, 1 + def_index.index()); + if position == u32::MAX { + debug!("Index::lookup: position=u32::MAX"); + None + } else { + debug!("Index::lookup: position={:?}", position); + Some(Lazy::from_position(position as usize)) + } + } +} diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 291ee23ff7262..9273b064ba9ce 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -1,7 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(box_patterns)] -#![feature(core_intrinsics)] #![feature(crate_visibility_modifier)] #![feature(drain_filter)] #![feature(in_band_lifetimes)] @@ -12,7 +11,6 @@ #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(specialization)] -#![feature(stmt_expr_attributes)] #![recursion_limit="256"] @@ -26,15 +24,15 @@ extern crate rustc_data_structures; pub mod error_codes; +mod index; mod encoder; mod decoder; -mod dependency_format; mod cstore_impl; -mod foreign_modules; -mod link_args; -mod native_libs; mod schema; -mod table; +mod native_libs; +mod link_args; +mod foreign_modules; +mod dependency_format; pub mod creader; pub mod cstore; diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs index 4291f3a4ae34e..527d4421fca65 100644 --- a/src/librustc_metadata/link_args.rs +++ b/src/librustc_metadata/link_args.rs @@ -4,7 +4,7 @@ use rustc::ty::TyCtxt; use rustc_target::spec::abi::Abi; use syntax::symbol::sym; -crate fn collect(tcx: TyCtxt<'_>) -> Vec { +pub fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { args: Vec::new(), }; diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index a5298402dd411..ceba7cf0fe031 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -212,21 +212,19 @@ //! no means all of the necessary details. Take a look at the rest of //! metadata::locator or metadata::creader for all the juicy details! -use crate::cstore::MetadataBlob; +use crate::cstore::{MetadataRef, MetadataBlob}; use crate::creader::Library; use crate::schema::{METADATA_HEADER, rustc_version}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::MetadataRef; -use rustc::middle::cstore::{CrateSource, MetadataLoader}; -use rustc::session::{config, Session, CrateDisambiguator}; +use rustc::middle::cstore::MetadataLoader; +use rustc::session::{config, Session}; use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch}; use rustc::session::search_paths::PathKind; use rustc::util::nodemap::FxHashMap; use errors::DiagnosticBuilder; -use syntax::{span_err, span_fatal}; use syntax::symbol::{Symbol, sym}; use syntax::struct_span_err; use syntax_pos::Span; @@ -247,15 +245,16 @@ use rustc_data_structures::owning_ref::OwningRef; use log::{debug, info, warn}; #[derive(Clone)] -crate struct CrateMismatch { +pub struct CrateMismatch { path: PathBuf, got: String, } #[derive(Clone)] -crate struct Context<'a> { +pub struct Context<'a> { pub sess: &'a Session, pub span: Span, + pub ident: Symbol, pub crate_name: Symbol, pub hash: Option<&'a Svh>, pub extra_filename: Option<&'a str>, @@ -263,7 +262,7 @@ crate struct Context<'a> { pub target: &'a Target, pub triple: TargetTriple, pub filesearch: FileSearch<'a>, - pub root: Option<&'a CratePaths>, + pub root: &'a Option, pub rejected_via_hash: Vec, pub rejected_via_triple: Vec, pub rejected_via_kind: Vec, @@ -274,9 +273,11 @@ crate struct Context<'a> { pub metadata_loader: &'a dyn MetadataLoader, } -crate struct CratePaths { - pub name: Symbol, - pub source: CrateSource, +pub struct CratePaths { + pub ident: String, + pub dylib: Option, + pub rlib: Option, + pub rmeta: Option, } #[derive(Copy, Clone, PartialEq)] @@ -296,8 +297,14 @@ impl fmt::Display for CrateFlavor { } } +impl CratePaths { + fn paths(&self) -> Vec { + self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).cloned().collect() + } +} + impl<'a> Context<'a> { - crate fn reset(&mut self) { + pub fn reset(&mut self) { self.rejected_via_hash.clear(); self.rejected_via_triple.clear(); self.rejected_via_kind.clear(); @@ -305,7 +312,7 @@ impl<'a> Context<'a> { self.rejected_via_filename.clear(); } - crate fn maybe_load_library_crate(&mut self) -> Option { + pub fn maybe_load_library_crate(&mut self) -> Option { let mut seen_paths = FxHashSet::default(); match self.extra_filename { Some(s) => self.find_library_crate(s, &mut seen_paths) @@ -314,10 +321,10 @@ impl<'a> Context<'a> { } } - crate fn report_errs(self) -> ! { + pub fn report_errs(self) -> ! { let add = match self.root { - None => String::new(), - Some(r) => format!(" which `{}` depends on", r.name), + &None => String::new(), + &Some(ref r) => format!(" which `{}` depends on", r.ident), }; let mut msg = "the following crate versions were found:".to_string(); let mut err = if !self.rejected_via_hash.is_empty() { @@ -325,18 +332,18 @@ impl<'a> Context<'a> { self.span, E0460, "found possibly newer version of crate `{}`{}", - self.crate_name, + self.ident, add); err.note("perhaps that crate needs to be recompiled?"); let mismatches = self.rejected_via_hash.iter(); for &CrateMismatch { ref path, .. } in mismatches { - msg.push_str(&format!("\ncrate `{}`: {}", self.crate_name, path.display())); + msg.push_str(&format!("\ncrate `{}`: {}", self.ident, path.display())); } match self.root { - None => {} - Some(r) => { - for path in r.source.paths() { - msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display())); + &None => {} + &Some(ref r) => { + for path in r.paths().iter() { + msg.push_str(&format!("\ncrate `{}`: {}", r.ident, path.display())); } } } @@ -348,13 +355,13 @@ impl<'a> Context<'a> { E0461, "couldn't find crate `{}` \ with expected target triple {}{}", - self.crate_name, + self.ident, self.triple, add); let mismatches = self.rejected_via_triple.iter(); for &CrateMismatch { ref path, ref got } in mismatches { msg.push_str(&format!("\ncrate `{}`, target triple {}: {}", - self.crate_name, + self.ident, got, path.display())); } @@ -365,12 +372,12 @@ impl<'a> Context<'a> { self.span, E0462, "found staticlib `{}` instead of rlib or dylib{}", - self.crate_name, + self.ident, add); err.help("please recompile that crate using --crate-type lib"); let mismatches = self.rejected_via_kind.iter(); for &CrateMismatch { ref path, .. } in mismatches { - msg.push_str(&format!("\ncrate `{}`: {}", self.crate_name, path.display())); + msg.push_str(&format!("\ncrate `{}`: {}", self.ident, path.display())); } err.note(&msg); err @@ -380,14 +387,14 @@ impl<'a> Context<'a> { E0514, "found crate `{}` compiled by an incompatible version \ of rustc{}", - self.crate_name, + self.ident, add); err.help(&format!("please recompile that crate using this compiler ({})", rustc_version())); let mismatches = self.rejected_via_version.iter(); for &CrateMismatch { ref path, ref got } in mismatches { msg.push_str(&format!("\ncrate `{}` compiled by {}: {}", - self.crate_name, + self.ident, got, path.display())); } @@ -398,10 +405,10 @@ impl<'a> Context<'a> { self.span, E0463, "can't find crate for `{}`{}", - self.crate_name, + self.ident, add); - if (self.crate_name == sym::std || self.crate_name == sym::core) + if (self.ident == sym::std || self.ident == sym::core) && self.triple != TargetTriple::from_triple(config::host_triple()) { err.note(&format!("the `{}` target may not be installed", self.triple)); } @@ -528,8 +535,18 @@ impl<'a> Context<'a> { // search is being performed for. let mut libraries = FxHashMap::default(); for (_hash, (rlibs, rmetas, dylibs)) in candidates { - if let Some((svh, lib)) = self.extract_lib(rlibs, rmetas, dylibs) { - libraries.insert(svh, lib); + let mut slot = None; + let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot); + let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot); + let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot); + if let Some((h, m)) = slot { + libraries.insert(h, + Library { + dylib, + rlib, + rmeta, + metadata: m, + }); } } @@ -547,7 +564,7 @@ impl<'a> Context<'a> { self.crate_name); let candidates = libraries.iter().filter_map(|(_, lib)| { let crate_name = &lib.metadata.get_root().name.as_str(); - match &(&lib.source.dylib, &lib.source.rlib) { + match &(&lib.dylib, &lib.rlib) { &(&Some((ref pd, _)), &Some((ref pr, _))) => { Some(format!("\ncrate `{}`: {}\n{:>padding$}", crate_name, @@ -568,21 +585,6 @@ impl<'a> Context<'a> { } } - fn extract_lib( - &mut self, - rlibs: FxHashMap, - rmetas: FxHashMap, - dylibs: FxHashMap, - ) -> Option<(Svh, Library)> { - let mut slot = None; - let source = CrateSource { - rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot), - rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot), - dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot), - }; - slot.map(|(svh, metadata)| (svh, Library { source, metadata })) - } - // Attempts to extract *one* library from the set `m`. If the set has no // elements, `None` is returned. If the set has more than one element, then // the errors and notes are emitted about the set of libraries. @@ -827,8 +829,23 @@ impl<'a> Context<'a> { } }; - // Extract the dylib/rlib/rmeta triple. - self.extract_lib(rlibs, rmetas, dylibs).map(|(_, lib)| lib) + // Extract the rlib/dylib pair. + let mut slot = None; + let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot); + let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot); + let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot); + + if rlib.is_none() && rmeta.is_none() && dylib.is_none() { + return None; + } + slot.map(|(_, metadata)| + Library { + dylib, + rlib, + rmeta, + metadata, + } + ) } } @@ -912,87 +929,10 @@ fn get_metadata_section_imp(target: &Target, } } -/// Look for a plugin registrar. Returns its library path and crate disambiguator. -pub fn find_plugin_registrar( - sess: &Session, - metadata_loader: &dyn MetadataLoader, - span: Span, - name: Symbol, -) -> Option<(PathBuf, CrateDisambiguator)> { - info!("find plugin registrar `{}`", name); - let target_triple = sess.opts.target_triple.clone(); - let host_triple = TargetTriple::from_triple(config::host_triple()); - let is_cross = target_triple != host_triple; - let mut target_only = false; - let mut locate_ctxt = Context { - sess, - span, - crate_name: name, - hash: None, - extra_filename: None, - filesearch: sess.host_filesearch(PathKind::Crate), - target: &sess.host, - triple: host_triple, - root: None, - rejected_via_hash: vec![], - rejected_via_triple: vec![], - rejected_via_kind: vec![], - rejected_via_version: vec![], - rejected_via_filename: vec![], - should_match_name: true, - is_proc_macro: None, - metadata_loader, - }; - - let library = locate_ctxt.maybe_load_library_crate().or_else(|| { - if !is_cross { - return None - } - // Try loading from target crates. This will abort later if we - // try to load a plugin registrar function, - target_only = true; - - locate_ctxt.target = &sess.target.target; - locate_ctxt.triple = target_triple; - locate_ctxt.filesearch = sess.target_filesearch(PathKind::Crate); - - locate_ctxt.maybe_load_library_crate() - }); - let library = match library { - Some(l) => l, - None => locate_ctxt.report_errs(), - }; - - if target_only { - // Need to abort before syntax expansion. - let message = format!("plugin `{}` is not available for triple `{}` \ - (only found {})", - name, - config::host_triple(), - sess.opts.target_triple); - span_fatal!(sess, span, E0456, "{}", &message); - } - - match library.source.dylib { - Some(dylib) => { - Some((dylib.0, library.metadata.get_root().disambiguator)) - } - None => { - span_err!(sess, span, E0457, - "plugin `{}` only found in rlib format, but must be available \ - in dylib format", - name); - // No need to abort because the loading code will just ignore this - // empty dylib. - None - } - } -} - /// A diagnostic function for dumping crate metadata to an output stream. pub fn list_file_metadata(target: &Target, path: &Path, - metadata_loader: &dyn MetadataLoader, + loader: &dyn MetadataLoader, out: &mut dyn io::Write) -> io::Result<()> { let filename = path.file_name().unwrap().to_str().unwrap(); @@ -1003,7 +943,7 @@ pub fn list_file_metadata(target: &Target, } else { CrateFlavor::Dylib }; - match get_metadata_section(target, flavor, path, metadata_loader) { + match get_metadata_section(target, flavor, path, loader) { Ok(metadata) => metadata.list_crate_metadata(out), Err(msg) => write!(out, "{}\n", msg), } diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index a58db6a903bb9..fe215d9c7999e 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -11,7 +11,7 @@ use syntax::feature_gate::{self, GateIssue}; use syntax::symbol::{kw, sym, Symbol}; use syntax::{span_err, struct_span_err}; -crate fn collect(tcx: TyCtxt<'_>) -> Vec { +pub fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { tcx, libs: Vec::new(), @@ -21,7 +21,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec { return collector.libs; } -crate fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { +pub fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { match lib.cfg { Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None), None => true, @@ -73,7 +73,6 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> { "static-nobundle" => cstore::NativeStaticNobundle, "dylib" => cstore::NativeUnknown, "framework" => cstore::NativeFramework, - "raw-dylib" => cstore::NativeRawDylib, k => { struct_span_err!(self.tcx.sess, item.span(), E0458, "unknown kind: `{}`", k) @@ -170,14 +169,6 @@ impl Collector<'tcx> { GateIssue::Language, "kind=\"static-nobundle\" is unstable"); } - if lib.kind == cstore::NativeRawDylib && - !self.tcx.features().raw_dylib { - feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, - sym::raw_dylib, - span.unwrap_or_else(|| syntax_pos::DUMMY_SP), - GateIssue::Language, - "kind=\"raw-dylib\" is unstable"); - } self.libs.push(lib); } @@ -198,10 +189,12 @@ impl Collector<'tcx> { self.tcx.sess.err(&format!("renaming of the library `{}` was specified, \ however this crate contains no `#[link(...)]` \ attributes referencing this library.", name)); - } else if !renames.insert(name) { + } else if renames.contains(name) { self.tcx.sess.err(&format!("multiple renamings were \ specified for library `{}` .", name)); + } else { + renames.insert(name); } } } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index ad39aa34fd5c8..4be70c6203569 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -1,4 +1,4 @@ -use crate::table::PerDefTable; +use crate::index; use rustc::hir; use rustc::hir::def::{self, CtorKind}; @@ -11,19 +11,17 @@ use rustc::session::CrateDisambiguator; use rustc::session::config::SymbolManglingVersion; use rustc::ty::{self, Ty, ReprOptions}; use rustc_target::spec::{PanicStrategy, TargetTriple}; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::svh::Svh; -use rustc_serialize::Encodable; use syntax::{ast, attr}; use syntax::edition::Edition; use syntax::symbol::Symbol; use syntax_pos::{self, Span}; use std::marker::PhantomData; -use std::num::NonZeroUsize; -crate fn rustc_version() -> String { +pub fn rustc_version() -> String { format!("rustc {}", option_env!("CFG_VERSION").unwrap_or("unknown version")) } @@ -31,7 +29,7 @@ crate fn rustc_version() -> String { /// Metadata encoding version. /// N.B., increment this if you change the format of metadata such that /// the rustc version can't be found to compare with `rustc_version()`. -const METADATA_VERSION: u8 = 4; +pub const METADATA_VERSION: u8 = 4; /// Metadata header which includes `METADATA_VERSION`. /// To get older versions of rustc to ignore this metadata, @@ -41,12 +39,12 @@ const METADATA_VERSION: u8 = 4; /// This header is followed by the position of the `CrateRoot`, /// which is encoded as a 32-bit big-endian unsigned integer, /// and further followed by the rustc version string. -crate const METADATA_HEADER: &[u8; 12] = +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). -crate trait LazyMeta { +pub trait LazyMeta { type Meta: Copy + 'static; /// Returns the minimum encoded size. @@ -54,7 +52,7 @@ crate trait LazyMeta { fn min_size(meta: Self::Meta) -> usize; } -impl LazyMeta for T { +impl LazyMeta for T { type Meta = (); fn min_size(_: ()) -> usize { @@ -63,7 +61,7 @@ impl LazyMeta for T { } } -impl LazyMeta for [T] { +impl LazyMeta for [T] { type Meta = usize; fn min_size(len: usize) -> usize { @@ -100,17 +98,17 @@ impl LazyMeta for [T] { #[must_use] // FIXME(#59875) the `Meta` parameter only exists to dodge // invariance wrt `T` (coming from the `meta: T::Meta` field). -crate struct Lazy::Meta> +pub struct Lazy::Meta> where T: ?Sized + LazyMeta, Meta: 'static + Copy, { - pub position: NonZeroUsize, + pub position: usize, pub meta: Meta, _marker: PhantomData, } impl Lazy { - crate fn from_position_and_meta(position: NonZeroUsize, meta: T::Meta) -> Lazy { + pub fn from_position_and_meta(position: usize, meta: T::Meta) -> Lazy { Lazy { position, meta, @@ -119,15 +117,15 @@ impl Lazy { } } -impl Lazy { - crate fn from_position(position: NonZeroUsize) -> Lazy { +impl Lazy { + pub fn from_position(position: usize) -> Lazy { Lazy::from_position_and_meta(position, ()) } } -impl Lazy<[T]> { - crate fn empty() -> Lazy<[T]> { - Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0) +impl Lazy<[T]> { + pub fn empty() -> Lazy<[T]> { + Lazy::from_position_and_meta(0, 0) } } @@ -143,32 +141,22 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy /// Encoding / decoding state for `Lazy`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] -crate enum LazyState { +pub enum LazyState { /// Outside of a metadata node. NoNode, /// Inside a metadata node, and before any `Lazy`. /// The position is that of the node itself. - NodeStart(NonZeroUsize), + NodeStart(usize), /// Inside a metadata node, with a previous `Lazy`. /// The position is a conservative estimate of where that /// previous `Lazy` would end (see their comments). - Previous(NonZeroUsize), -} - -// FIXME(#59875) `Lazy!(T)` replaces `Lazy`, passing the `Meta` parameter -// manually, instead of relying on the default, to get the correct variance. -// Only needed when `T` itself contains a parameter (e.g. `'tcx`). -macro_rules! Lazy { - (Table<$T:ty>) => {Lazy, usize>}; - (PerDefTable<$T:ty>) => {Lazy, usize>}; - ([$T:ty]) => {Lazy<[$T], usize>}; - ($T:ty) => {Lazy<$T, ()>}; + Previous(usize), } #[derive(RustcEncodable, RustcDecodable)] -crate struct CrateRoot<'tcx> { +pub struct CrateRoot<'tcx> { pub name: Symbol, pub triple: TargetTriple, pub extra_filename: String, @@ -194,10 +182,10 @@ crate struct CrateRoot<'tcx> { pub source_map: Lazy<[syntax_pos::SourceFile]>, pub def_path_table: Lazy, pub impls: Lazy<[TraitImpls]>, - pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), + pub exported_symbols: Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]>, pub interpret_alloc_index: Lazy<[u32]>, - pub per_def: LazyPerDefTables<'tcx>, + pub entries_index: Lazy<[index::Index<'tcx>]>, /// The DefIndex's of any proc macros delcared by /// this crate @@ -214,7 +202,7 @@ crate struct CrateRoot<'tcx> { } #[derive(RustcEncodable, RustcDecodable)] -crate struct CrateDep { +pub struct CrateDep { pub name: ast::Name, pub hash: Svh, pub kind: DepKind, @@ -222,37 +210,34 @@ crate struct CrateDep { } #[derive(RustcEncodable, RustcDecodable)] -crate struct TraitImpls { +pub struct TraitImpls { pub trait_id: (u32, DefIndex), pub impls: Lazy<[DefIndex]>, } #[derive(RustcEncodable, RustcDecodable)] -crate struct LazyPerDefTables<'tcx> { - pub kind: Lazy!(PerDefTable)>), - pub visibility: Lazy!(PerDefTable>), - pub span: Lazy!(PerDefTable>), - pub attributes: Lazy!(PerDefTable>), - pub children: Lazy!(PerDefTable>), - pub stability: Lazy!(PerDefTable>), - pub deprecation: Lazy!(PerDefTable>), - - pub ty: Lazy!(PerDefTable)>), - pub fn_sig: Lazy!(PerDefTable)>), - pub impl_trait_ref: Lazy!(PerDefTable)>), - pub inherent_impls: Lazy!(PerDefTable>), - pub variances: Lazy!(PerDefTable>), - pub generics: Lazy!(PerDefTable>), - pub predicates: Lazy!(PerDefTable)>), - pub predicates_defined_on: Lazy!(PerDefTable)>), - pub super_predicates: Lazy!(PerDefTable)>), - - pub mir: Lazy!(PerDefTable)>), - pub promoted_mir: Lazy!(PerDefTable>)>), +pub struct Entry<'tcx> { + pub kind: EntryKind<'tcx>, + pub visibility: Lazy, + pub span: Lazy, + pub attributes: Lazy<[ast::Attribute]>, + pub children: Lazy<[DefIndex]>, + pub stability: Option>, + pub deprecation: Option>, + + pub ty: Option>>, + 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)] -crate enum EntryKind<'tcx> { +pub enum EntryKind<'tcx> { Const(ConstQualif, Lazy), ImmStatic, MutStatic, @@ -267,78 +252,89 @@ crate enum EntryKind<'tcx> { OpaqueTy, Enum(ReprOptions), Field, - Variant(Lazy), - Struct(Lazy, ReprOptions), - Union(Lazy, ReprOptions), - Fn(Lazy), - ForeignFn(Lazy), + Variant(Lazy>), + Struct(Lazy>, ReprOptions), + Union(Lazy>, ReprOptions), + Fn(Lazy>), + ForeignFn(Lazy>), Mod(Lazy), MacroDef(Lazy), - Closure, - Generator(Lazy!(GeneratorData<'tcx>)), - Trait(Lazy), - Impl(Lazy), - Method(Lazy), + Closure(Lazy>), + Generator(Lazy>), + Trait(Lazy>), + Impl(Lazy>), + Method(Lazy>), AssocType(AssocContainer), AssocOpaqueTy(AssocContainer), AssocConst(AssocContainer, ConstQualif, Lazy), - TraitAlias, + TraitAlias(Lazy>), } /// Additional data for EntryKind::Const and EntryKind::AssocConst #[derive(Clone, Copy, RustcEncodable, RustcDecodable)] -crate struct ConstQualif { +pub struct ConstQualif { pub mir: u8, + pub ast_promotable: bool, } /// Contains a constant which has been rendered to a String. /// Used by rustdoc. #[derive(RustcEncodable, RustcDecodable)] -crate struct RenderedConst(pub String); +pub struct RenderedConst(pub String); #[derive(RustcEncodable, RustcDecodable)] -crate struct ModData { +pub struct ModData { pub reexports: Lazy<[def::Export]>, } #[derive(RustcEncodable, RustcDecodable)] -crate struct MacroDef { +pub struct MacroDef { pub body: String, pub legacy: bool, } #[derive(RustcEncodable, RustcDecodable)] -crate struct FnData { +pub struct FnData<'tcx> { pub asyncness: hir::IsAsync, pub constness: hir::Constness, pub param_names: Lazy<[ast::Name]>, + pub sig: Lazy>, } #[derive(RustcEncodable, RustcDecodable)] -crate struct VariantData { +pub struct VariantData<'tcx> { pub ctor_kind: CtorKind, pub discr: ty::VariantDiscr, /// If this is unit or tuple-variant/struct, then this is the index of the ctor id. pub ctor: Option, + /// If this is a tuple struct or variant + /// ctor, this is its "function" signature. + pub ctor_sig: Option>>, } #[derive(RustcEncodable, RustcDecodable)] -crate struct TraitData { +pub struct TraitData<'tcx> { pub unsafety: hir::Unsafety, pub paren_sugar: bool, pub has_auto_impl: bool, pub is_marker: bool, + pub super_predicates: Lazy>, +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct TraitAliasData<'tcx> { + pub super_predicates: Lazy>, } #[derive(RustcEncodable, RustcDecodable)] -crate struct ImplData { +pub struct ImplData<'tcx> { pub polarity: ty::ImplPolarity, pub defaultness: hir::Defaultness, pub parent_impl: Option, /// This is `Some` only for impls of `CoerceUnsized`. - // FIXME(eddyb) perhaps compute this on the fly if cheap enough? pub coerce_unsized_info: Option, + pub trait_ref: Option>>, } @@ -346,7 +342,7 @@ crate struct ImplData { /// is a trait or an impl and whether, in a trait, it has /// a default, or an in impl, whether it's marked "default". #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] -crate enum AssocContainer { +pub enum AssocContainer { TraitRequired, TraitWithDefault, ImplDefault, @@ -354,7 +350,7 @@ crate enum AssocContainer { } impl AssocContainer { - crate fn with_def_id(&self, def_id: DefId) -> ty::AssocItemContainer { + pub fn with_def_id(&self, def_id: DefId) -> ty::AssocItemContainer { match *self { AssocContainer::TraitRequired | AssocContainer::TraitWithDefault => ty::TraitContainer(def_id), @@ -364,7 +360,7 @@ impl AssocContainer { } } - crate fn defaultness(&self) -> hir::Defaultness { + pub fn defaultness(&self) -> hir::Defaultness { match *self { AssocContainer::TraitRequired => hir::Defaultness::Default { has_value: false, @@ -381,17 +377,22 @@ impl AssocContainer { } #[derive(RustcEncodable, RustcDecodable)] -crate struct MethodData { - pub fn_data: FnData, +pub struct MethodData<'tcx> { + pub fn_data: FnData<'tcx>, pub container: AssocContainer, pub has_self: bool, } #[derive(RustcEncodable, RustcDecodable)] -crate struct GeneratorData<'tcx> { +pub struct ClosureData<'tcx> { + pub sig: Lazy>, +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct GeneratorData<'tcx> { pub layout: mir::GeneratorLayout<'tcx>, } // Tags used for encoding Spans: -crate const TAG_VALID_SPAN: u8 = 0; -crate const TAG_INVALID_SPAN: u8 = 1; +pub const TAG_VALID_SPAN: u8 = 0; +pub const TAG_INVALID_SPAN: u8 = 1; diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs deleted file mode 100644 index e164c28c953bc..0000000000000 --- a/src/librustc_metadata/table.rs +++ /dev/null @@ -1,239 +0,0 @@ -use crate::decoder::Metadata; -use crate::schema::*; - -use rustc::hir::def_id::{DefId, DefIndex}; -use rustc_serialize::{Encodable, opaque::Encoder}; -use std::convert::TryInto; -use std::marker::PhantomData; -use std::num::NonZeroUsize; -use log::debug; - -/// Helper trait, for encoding to, and decoding from, a fixed number of bytes. -/// Used mainly for Lazy positions and lengths. -/// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`, -/// but this has no impact on safety. -crate trait FixedSizeEncoding: Default { - const BYTE_LEN: usize; - - // FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead, - // once that starts being allowed by the compiler (i.e. lazy normalization). - fn from_bytes(b: &[u8]) -> Self; - fn write_to_bytes(self, b: &mut [u8]); - - // FIXME(eddyb) make these generic functions, or at least defaults here. - // (same problem as above, needs `[u8; Self::BYTE_LEN]`) - // For now, a macro (`fixed_size_encoding_byte_len_and_defaults`) is used. - - /// Read a `Self` value (encoded as `Self::BYTE_LEN` bytes), - /// from `&b[i * Self::BYTE_LEN..]`, returning `None` if `i` - /// is not in bounds, or `Some(Self::from_bytes(...))` otherwise. - fn maybe_read_from_bytes_at(b: &[u8], i: usize) -> Option; - /// Write a `Self` value (encoded as `Self::BYTE_LEN` bytes), - /// at `&mut b[i * Self::BYTE_LEN..]`, using `Self::write_to_bytes`. - fn write_to_bytes_at(self, b: &mut [u8], i: usize); -} - -// HACK(eddyb) this shouldn't be needed (see comments on the methods above). -macro_rules! fixed_size_encoding_byte_len_and_defaults { - ($byte_len:expr) => { - const BYTE_LEN: usize = $byte_len; - fn maybe_read_from_bytes_at(b: &[u8], i: usize) -> Option { - const BYTE_LEN: usize = $byte_len; - // HACK(eddyb) ideally this would be done with fully safe code, - // but slicing `[u8]` with `i * N..` is optimized worse, due to the - // possibility of `i * N` overflowing, than indexing `[[u8; N]]`. - let b = unsafe { - std::slice::from_raw_parts( - b.as_ptr() as *const [u8; BYTE_LEN], - b.len() / BYTE_LEN, - ) - }; - b.get(i).map(|b| FixedSizeEncoding::from_bytes(b)) - } - fn write_to_bytes_at(self, b: &mut [u8], i: usize) { - const BYTE_LEN: usize = $byte_len; - // HACK(eddyb) ideally this would be done with fully safe code, - // see similar comment in `read_from_bytes_at` for why it can't yet. - let b = unsafe { - std::slice::from_raw_parts_mut( - b.as_mut_ptr() as *mut [u8; BYTE_LEN], - b.len() / BYTE_LEN, - ) - }; - self.write_to_bytes(&mut b[i]); - } - } -} - -impl FixedSizeEncoding for u32 { - fixed_size_encoding_byte_len_and_defaults!(4); - - fn from_bytes(b: &[u8]) -> Self { - let mut bytes = [0; Self::BYTE_LEN]; - bytes.copy_from_slice(&b[..Self::BYTE_LEN]); - Self::from_le_bytes(bytes) - } - - fn write_to_bytes(self, b: &mut [u8]) { - b[..Self::BYTE_LEN].copy_from_slice(&self.to_le_bytes()); - } -} - -// NOTE(eddyb) there could be an impl for `usize`, which would enable a more -// generic `Lazy` impl, but in the general case we might not need / want to -// fit every `usize` in `u32`. -impl FixedSizeEncoding for Option> { - fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN); - - fn from_bytes(b: &[u8]) -> Self { - Some(Lazy::from_position(NonZeroUsize::new(u32::from_bytes(b) as usize)?)) - } - - fn write_to_bytes(self, b: &mut [u8]) { - let position = self.map_or(0, |lazy| lazy.position.get()); - let position: u32 = position.try_into().unwrap(); - - position.write_to_bytes(b) - } -} - -impl FixedSizeEncoding for Option> { - fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN * 2); - - fn from_bytes(b: &[u8]) -> Self { - Some(Lazy::from_position_and_meta( - >>::from_bytes(b)?.position, - u32::from_bytes(&b[u32::BYTE_LEN..]) as usize, - )) - } - - fn write_to_bytes(self, b: &mut [u8]) { - self.map(|lazy| Lazy::::from_position(lazy.position)) - .write_to_bytes(b); - - let len = self.map_or(0, |lazy| lazy.meta); - let len: u32 = len.try_into().unwrap(); - - len.write_to_bytes(&mut b[u32::BYTE_LEN..]); - } -} - -/// Random-access table (i.e. offeringconstant-time `get`/`set`), similar to -/// `Vec>`, but without requiring encoding or decoding all the values -/// eagerly and in-order. -/// A total of `(max_idx + 1) * as FixedSizeEncoding>::BYTE_LEN` bytes -/// are used for a table, where `max_idx` is the largest index passed to `set`. -// FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box>` would be used -// when building it, and `Lazy>` or `&Table` when reading it. -// (not sure if that is possible given that the `Vec` is being resized now) -crate struct Table where Option: FixedSizeEncoding { - // FIXME(eddyb) store `[u8; >::BYTE_LEN]` instead of `u8` in `Vec`, - // once that starts being allowed by the compiler (i.e. lazy normalization). - bytes: Vec, - _marker: PhantomData, -} - -impl Default for Table where Option: FixedSizeEncoding { - fn default() -> Self { - Table { - bytes: vec![], - _marker: PhantomData, - } - } -} - -impl Table where Option: FixedSizeEncoding { - crate fn set(&mut self, i: usize, value: T) { - // FIXME(eddyb) investigate more compact encodings for sparse tables. - // On the PR @michaelwoerister mentioned: - // > Space requirements could perhaps be optimized by using the HAMT `popcnt` - // > trick (i.e. divide things into buckets of 32 or 64 items and then - // > store bit-masks of which item in each bucket is actually serialized). - let needed = (i + 1) * >::BYTE_LEN; - if self.bytes.len() < needed { - self.bytes.resize(needed, 0); - } - - Some(value).write_to_bytes_at(&mut self.bytes, i); - } - - crate fn encode(&self, buf: &mut Encoder) -> Lazy { - let pos = buf.position(); - buf.emit_raw_bytes(&self.bytes); - Lazy::from_position_and_meta( - NonZeroUsize::new(pos as usize).unwrap(), - self.bytes.len(), - ) - } -} - -impl LazyMeta for Table where Option: FixedSizeEncoding { - type Meta = usize; - - fn min_size(len: usize) -> usize { - len - } -} - -impl Lazy> where Option: FixedSizeEncoding { - /// Given the metadata, extract out the value at a particular index (if any). - #[inline(never)] - crate fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>( - &self, - metadata: M, - i: usize, - ) -> Option { - debug!("Table::lookup: index={:?} len={:?}", i, self.meta); - - let start = self.position.get(); - let bytes = &metadata.raw_bytes()[start..start + self.meta]; - >::maybe_read_from_bytes_at(bytes, i)? - } -} - -/// Like a `Table` but using `DefIndex` instead of `usize` as keys. -// FIXME(eddyb) replace by making `Table` behave like `IndexVec`, -// and by using `newtype_index!` to define `DefIndex`. -crate struct PerDefTable(Table) where Option: FixedSizeEncoding; - -impl Default for PerDefTable where Option: FixedSizeEncoding { - fn default() -> Self { - PerDefTable(Table::default()) - } -} - -impl PerDefTable where Option: FixedSizeEncoding { - crate fn set(&mut self, def_id: DefId, value: T) { - assert!(def_id.is_local()); - self.0.set(def_id.index.index(), value); - } - - crate fn encode(&self, buf: &mut Encoder) -> Lazy { - let lazy = self.0.encode(buf); - Lazy::from_position_and_meta(lazy.position, lazy.meta) - } -} - -impl LazyMeta for PerDefTable where Option: FixedSizeEncoding { - type Meta = as LazyMeta>::Meta; - - fn min_size(meta: Self::Meta) -> usize { - Table::::min_size(meta) - } -} - -impl Lazy> where Option: FixedSizeEncoding { - fn as_table(&self) -> Lazy> { - Lazy::from_position_and_meta(self.position, self.meta) - } - - /// Given the metadata, extract out the value at a particular DefIndex (if any). - #[inline(never)] - crate fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>( - &self, - metadata: M, - def_index: DefIndex, - ) -> Option { - self.as_table().get(metadata, def_index.index()) - } -} diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index f0cdcf2136bfa..f296753a0304c 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -19,7 +19,6 @@ polonius-engine = "0.10.0" rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } -rustc_index = { path = "../librustc_index" } rustc_errors = { path = "../librustc_errors" } rustc_lexer = { path = "../librustc_lexer" } rustc_serialize = { path = "../libserialize", package = "serialize" } diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index 98641031c1787..db19cbc3175f8 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -8,8 +8,8 @@ use rustc::mir::visit::{PlaceContext, Visitor, NonUseContext, MutatingUseContext use rustc::mir::{self, Location, Body, Local}; use rustc::ty::{RegionVid, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; -use rustc_index::vec::IndexVec; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::indexed_vec::IndexVec; +use rustc_data_structures::bit_set::BitSet; use std::fmt; use std::ops::Index; @@ -315,7 +315,10 @@ impl<'a, 'tcx> GatherBorrows<'a, 'tcx> { // TEMP = &foo // // so extract `temp`. - let temp = if let Some(temp) = assigned_place.as_local() { + let temp = if let &mir::Place { + base: mir::PlaceBase::Local(temp), + projection: box [], + } = assigned_place { temp } else { span_bug!( diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 36db68a3372eb..7d5d58ed28468 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -1,6 +1,5 @@ use rustc::hir; use rustc::hir::def_id::DefId; -use rustc::hir::{AsyncGeneratorKind, GeneratorKind}; use rustc::mir::{ self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local, LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue, @@ -8,7 +7,7 @@ use rustc::mir::{ }; use rustc::ty::{self, Ty}; use rustc_data_structures::fx::FxHashSet; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use rustc_errors::{Applicability, DiagnosticBuilder}; use syntax_pos::Span; use syntax::source_map::DesugaringKind; @@ -78,7 +77,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .last() .unwrap(); - if !self.uninitialized_error_reported.insert(root_place) { + if self.uninitialized_error_reported.contains(&root_place) { debug!( "report_use_of_moved_or_uninitialized place: error about {:?} suppressed", root_place @@ -86,6 +85,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return; } + self.uninitialized_error_reported.insert(root_place); + let item_msg = match self.describe_place_with_options(used_place, IncludingDowncast(true)) { Some(name) => format!("`{}`", name), @@ -239,8 +240,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } } - let span = if let Some(local) = place.as_local() { - let decl = &self.body.local_decls[local]; + let span = if let Place { + base: PlaceBase::Local(local), + projection: box [], + } = place { + let decl = &self.body.local_decls[*local]; Some(decl.source_info.span) } else { None @@ -608,7 +612,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { projection, } = first_borrowed_place; - let mut cursor = projection.as_ref(); + let mut cursor = &**projection; while let [proj_base @ .., elem] = cursor { cursor = proj_base; @@ -632,7 +636,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { projection, } = second_borrowed_place; - let mut cursor = projection.as_ref(); + let mut cursor = &**projection; while let [proj_base @ .., elem] = cursor { cursor = proj_base; @@ -707,12 +711,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => drop_span, }; - let root_place_projection = self.infcx.tcx.intern_place_elems(root_place.projection); - if self.access_place_error_reported .contains(&(Place { base: root_place.base.clone(), - projection: root_place_projection, + projection: root_place.projection.to_vec().into_boxed_slice(), }, borrow_span)) { debug!( @@ -725,7 +727,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.access_place_error_reported .insert((Place { base: root_place.base.clone(), - projection: root_place_projection, + projection: root_place.projection.to_vec().into_boxed_slice(), }, borrow_span)); if let StorageDeadOrDrop::Destructor(dropped_ty) = @@ -748,11 +750,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0)); let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place); - debug!( - "report_borrowed_value_does_not_live_long_enough(place_desc: {:?}, explanation: {:?})", - place_desc, - explanation - ); let err = match (place_desc, explanation) { (Some(_), _) if self.is_place_thread_local(root_place) => { self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span) @@ -786,25 +783,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .. }, ) if borrow_spans.for_closure() => self.report_escaping_closure_capture( - borrow_spans, - borrow_span, - region_name, - category, - span, - &format!("`{}`", name), - ), - ( - Some(ref name), - BorrowExplanation::MustBeValidFor { - category: category @ ConstraintCategory::OpaqueType, - from_closure: false, - ref region_name, - span, - .. - }, - - ) if borrow_spans.for_generator() => self.report_escaping_closure_capture( - borrow_spans, + borrow_spans.args_or_use(), borrow_span, region_name, category, @@ -1123,22 +1102,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; let (place_desc, note) = if let Some(place_desc) = opt_place_desc { - let local_kind = if let Some(local) = borrow.borrowed_place.as_local() { - match self.body.local_kind(local) { - LocalKind::ReturnPointer - | LocalKind::Temp => bug!("temporary or return pointer with a name"), - LocalKind::Var => "local variable ", - LocalKind::Arg - if !self.upvars.is_empty() - && local == Local::new(1) => { - "variable captured by `move` " - } - LocalKind::Arg => { - "function parameter " + let local_kind = match borrow.borrowed_place { + Place { + base: PlaceBase::Local(local), + projection: box [], + } => { + match self.body.local_kind(local) { + LocalKind::ReturnPointer + | LocalKind::Temp => bug!("temporary or return pointer with a name"), + LocalKind::Var => "local variable ", + LocalKind::Arg + if !self.upvars.is_empty() + && local == Local::new(1) => { + "variable captured by `move` " + } + LocalKind::Arg => { + "function parameter " + } } } - } else { - "local data " + _ => "local data ", }; ( format!("{}`{}`", local_kind, place_desc), @@ -1189,7 +1172,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn report_escaping_closure_capture( &mut self, - use_span: UseSpans, + args_span: Span, var_span: Span, fr_name: &RegionName, category: ConstraintCategory, @@ -1197,7 +1180,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { captured_var: &str, ) -> DiagnosticBuilder<'cx> { let tcx = self.infcx.tcx; - let args_span = use_span.args_or_use(); + let mut err = self.cannot_capture_in_long_lived_closure( args_span, captured_var, @@ -1217,25 +1200,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }, Err(_) => "move || ".to_string() }; - let kind = match use_span.generator_kind() { - Some(generator_kind) => match generator_kind { - GeneratorKind::Async(async_kind) => match async_kind { - AsyncGeneratorKind::Block => "async block", - AsyncGeneratorKind::Closure => "async closure", - _ => bug!("async block/closure expected, but async funtion found."), - }, - GeneratorKind::Gen => "generator", - } - None => "closure", - }; + err.span_suggestion( args_span, - &format!( - "to force the {} to take ownership of {} (and any \ - other referenced variables), use the `move` keyword", - kind, - captured_var - ), + &format!("to force the closure to take ownership of {} (and any \ + other referenced variables), use the `move` keyword", + captured_var), suggestion, Applicability::MachineApplicable, ); @@ -1244,9 +1214,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ConstraintCategory::Return => { err.span_note(constraint_span, "closure is returned here"); } - ConstraintCategory::OpaqueType => { - err.span_note(constraint_span, "generator is returned here"); - } ConstraintCategory::CallArgument => { fr_name.highlight_region_name(&mut err); err.span_note( @@ -1475,7 +1442,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { assigned_span: Span, err_place: &Place<'tcx>, ) { - let (from_arg, local_decl) = if let Some(local) = err_place.as_local() { + let (from_arg, local_decl) = if let Place { + base: PlaceBase::Local(local), + projection: box [], + } = *err_place { if let LocalKind::Arg = self.body.local_kind(local) { (true, Some(&self.body.local_decls[local])) } else { @@ -1635,8 +1605,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { reservation ); // Check that the initial assignment of the reserve location is into a temporary. - let mut target = match reservation.as_local() { - Some(local) if self.body.local_kind(local) == LocalKind::Temp => local, + let mut target = *match reservation { + Place { + base: PlaceBase::Local(local), + projection: box [], + } if self.body.local_kind(*local) == LocalKind::Temp => local, _ => return None, }; @@ -1648,122 +1621,127 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}", target, stmt ); - if let StatementKind::Assign(box(place, rvalue)) = &stmt.kind { - if let Some(assigned_to) = place.as_local() { - debug!( - "annotate_argument_and_return_for_borrow: assigned_to={:?} \ - rvalue={:?}", - assigned_to, rvalue - ); - // Check if our `target` was captured by a closure. - if let Rvalue::Aggregate( - box AggregateKind::Closure(def_id, substs), - operands, - ) = rvalue - { - for operand in operands { - let assigned_from = match operand { - Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { - assigned_from - } - _ => continue, - }; - debug!( - "annotate_argument_and_return_for_borrow: assigned_from={:?}", + if let StatementKind::Assign( + box( + Place { + base: PlaceBase::Local(assigned_to), + projection: box [], + }, + rvalue + ) + ) = &stmt.kind { + debug!( + "annotate_argument_and_return_for_borrow: assigned_to={:?} \ + rvalue={:?}", + assigned_to, rvalue + ); + // Check if our `target` was captured by a closure. + if let Rvalue::Aggregate( + box AggregateKind::Closure(def_id, substs), + operands, + ) = rvalue + { + for operand in operands { + let assigned_from = match operand { + Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { assigned_from - ); - - // Find the local from the operand. - let assigned_from_local = match assigned_from.local_or_deref_local() - { - Some(local) => local, - None => continue, - }; - - if assigned_from_local != target { - continue; } + _ => continue, + }; + debug!( + "annotate_argument_and_return_for_borrow: assigned_from={:?}", + assigned_from + ); - // If a closure captured our `target` and then assigned - // into a place then we should annotate the closure in - // case it ends up being assigned into the return place. - annotated_closure = self.annotate_fn_sig( - *def_id, - self.infcx.closure_sig(*def_id, *substs), - ); - debug!( - "annotate_argument_and_return_for_borrow: \ - annotated_closure={:?} assigned_from_local={:?} \ - assigned_to={:?}", - annotated_closure, assigned_from_local, assigned_to - ); - - if assigned_to == mir::RETURN_PLACE { - // If it was assigned directly into the return place, then - // return now. - return annotated_closure; - } else { - // Otherwise, update the target. - target = assigned_to; - } + // Find the local from the operand. + let assigned_from_local = match assigned_from.local_or_deref_local() { + Some(local) => local, + None => continue, + }; + + if assigned_from_local != target { + continue; } - // If none of our closure's operands matched, then skip to the next - // statement. - continue; + // If a closure captured our `target` and then assigned + // into a place then we should annotate the closure in + // case it ends up being assigned into the return place. + annotated_closure = self.annotate_fn_sig( + *def_id, + self.infcx.closure_sig(*def_id, *substs), + ); + debug!( + "annotate_argument_and_return_for_borrow: \ + annotated_closure={:?} assigned_from_local={:?} \ + assigned_to={:?}", + annotated_closure, assigned_from_local, assigned_to + ); + + if *assigned_to == mir::RETURN_PLACE { + // If it was assigned directly into the return place, then + // return now. + return annotated_closure; + } else { + // Otherwise, update the target. + target = *assigned_to; + } } - // Otherwise, look at other types of assignment. - let assigned_from = match rvalue { - Rvalue::Ref(_, _, assigned_from) => assigned_from, - Rvalue::Use(operand) => match operand { - Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { - assigned_from - } - _ => continue, - }, - _ => continue, - }; - debug!( - "annotate_argument_and_return_for_borrow: \ - assigned_from={:?}", - assigned_from, - ); + // If none of our closure's operands matched, then skip to the next + // statement. + continue; + } - // Find the local from the rvalue. - let assigned_from_local = match assigned_from.local_or_deref_local() { - Some(local) => local, - None => continue, - }; - debug!( - "annotate_argument_and_return_for_borrow: \ - assigned_from_local={:?}", - assigned_from_local, - ); + // Otherwise, look at other types of assignment. + let assigned_from = match rvalue { + Rvalue::Ref(_, _, assigned_from) => assigned_from, + Rvalue::Use(operand) => match operand { + Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { + assigned_from + } + _ => continue, + }, + _ => continue, + }; + debug!( + "annotate_argument_and_return_for_borrow: \ + assigned_from={:?}", + assigned_from, + ); - // Check if our local matches the target - if so, we've assigned our - // borrow to a new place. - if assigned_from_local != target { - continue; - } + // Find the local from the rvalue. + let assigned_from_local = match assigned_from.local_or_deref_local() { + Some(local) => local, + None => continue, + }; + debug!( + "annotate_argument_and_return_for_borrow: \ + assigned_from_local={:?}", + assigned_from_local, + ); - // If we assigned our `target` into a new place, then we should - // check if it was the return place. - debug!( - "annotate_argument_and_return_for_borrow: \ - assigned_from_local={:?} assigned_to={:?}", - assigned_from_local, assigned_to - ); - if assigned_to == mir::RETURN_PLACE { - // If it was then return the annotated closure if there was one, - // else, annotate this function. - return annotated_closure.or_else(fallback); - } + // Check if our local matches the target - if so, we've assigned our + // borrow to a new place. + if assigned_from_local != target { + continue; + } - // If we didn't assign into the return place, then we just update - // the target. - target = assigned_to; + // If we assigned our `target` into a new place, then we should + // check if it was the return place. + debug!( + "annotate_argument_and_return_for_borrow: \ + assigned_from_local={:?} assigned_to={:?}", + assigned_from_local, assigned_to + ); + if *assigned_to == mir::RETURN_PLACE { + // If it was then return the annotated closure if there was one, + // else, annotate this function. + return annotated_closure.or_else(fallback); } + + // If we didn't assign into the return place, then we just update + // the target. + target = *assigned_to; } } @@ -1774,37 +1752,38 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { target, terminator ); if let TerminatorKind::Call { - destination: Some((place, _)), + destination: Some((Place { + base: PlaceBase::Local(assigned_to), + projection: box [], + }, _)), args, .. } = &terminator.kind { - if let Some(assigned_to) = place.as_local() { + debug!( + "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}", + assigned_to, args + ); + for operand in args { + let assigned_from = match operand { + Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { + assigned_from + } + _ => continue, + }; debug!( - "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}", - assigned_to, args + "annotate_argument_and_return_for_borrow: assigned_from={:?}", + assigned_from, ); - for operand in args { - let assigned_from = match operand { - Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { - assigned_from - } - _ => continue, - }; + + if let Some(assigned_from_local) = assigned_from.local_or_deref_local() { debug!( - "annotate_argument_and_return_for_borrow: assigned_from={:?}", - assigned_from, + "annotate_argument_and_return_for_borrow: assigned_from_local={:?}", + assigned_from_local, ); - if let Some(assigned_from_local) = assigned_from.local_or_deref_local() { - debug!( - "annotate_argument_and_return_for_borrow: assigned_from_local={:?}", - assigned_from_local, - ); - - if assigned_to == mir::RETURN_PLACE && assigned_from_local == target { - return annotated_closure.or_else(fallback); - } + if *assigned_to == mir::RETURN_PLACE && assigned_from_local == target { + return annotated_closure.or_else(fallback); } } } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 4036e9db33b34..dc7e4b2206588 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1,7 +1,6 @@ use rustc::hir; use rustc::hir::def::Namespace; use rustc::hir::def_id::DefId; -use rustc::hir::GeneratorKind; use rustc::mir::{ AggregateKind, Constant, Field, Local, LocalKind, Location, Operand, Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, @@ -15,7 +14,7 @@ use syntax_pos::Span; use syntax::symbol::sym; use super::borrow_set::BorrowData; -use super::MirBorrowckCtxt; +use super::{MirBorrowckCtxt}; use crate::dataflow::move_paths::{InitLocation, LookupResult}; pub(super) struct IncludingDowncast(pub(super) bool); @@ -605,7 +604,7 @@ pub(super) enum UseSpans { // The access is caused by capturing a variable for a closure. ClosureUse { // This is true if the captured variable was from a generator. - generator_kind: Option, + is_generator: bool, // The span of the args of the closure, including the `move` keyword if // it's present. args_span: Span, @@ -632,13 +631,6 @@ impl UseSpans { } } - pub(super) fn generator_kind(self) -> Option { - match self { - UseSpans::ClosureUse { generator_kind, .. } => generator_kind, - _ => None, - } - } - // Add a span label to the arguments of the closure, if it exists. pub(super) fn args_span_label( self, @@ -664,7 +656,7 @@ impl UseSpans { /// Returns `false` if this place is not used in a closure. pub(super) fn for_closure(&self) -> bool { match *self { - UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_none(), + UseSpans::ClosureUse { is_generator, .. } => !is_generator, _ => false, } } @@ -672,7 +664,7 @@ impl UseSpans { /// Returns `false` if this place is not used in a generator. pub(super) fn for_generator(&self) -> bool { match *self { - UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_some(), + UseSpans::ClosureUse { is_generator, .. } => is_generator, _ => false, } } @@ -680,7 +672,7 @@ impl UseSpans { /// Describe the span associated with a use of a place. pub(super) fn describe(&self) -> String { match *self { - UseSpans::ClosureUse { generator_kind, .. } => if generator_kind.is_some() { + UseSpans::ClosureUse { is_generator, .. } => if is_generator { " in generator".to_string() } else { " in closure".to_string() @@ -802,20 +794,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let StatementKind::Assign( box(_, Rvalue::Aggregate(ref kind, ref places)) ) = stmt.kind { - let def_id = match kind { - box AggregateKind::Closure(def_id, _) - | box AggregateKind::Generator(def_id, _, _) => def_id, + let (def_id, is_generator) = match kind { + box AggregateKind::Closure(def_id, _) => (def_id, false), + box AggregateKind::Generator(def_id, _, _) => (def_id, true), _ => return OtherUse(stmt.source_info.span), }; debug!( - "move_spans: def_id={:?} places={:?}", - def_id, places + "move_spans: def_id={:?} is_generator={:?} places={:?}", + def_id, is_generator, places ); - if let Some((args_span, generator_kind, var_span)) - = self.closure_span(*def_id, moved_place, places) { + if let Some((args_span, var_span)) = self.closure_span(*def_id, moved_place, places) { return ClosureUse { - generator_kind, + is_generator, args_span, var_span, }; @@ -838,15 +829,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .get(location.statement_index) { Some(&Statement { - kind: StatementKind::Assign(box(ref place, _)), + kind: StatementKind::Assign(box(Place { + base: PlaceBase::Local(local), + projection: box [], + }, _)), .. - }) => { - if let Some(local) = place.as_local() { - local - } else { - return OtherUse(use_span); - } - } + }) => local, _ => return OtherUse(use_span), }; @@ -869,11 +857,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "borrow_spans: def_id={:?} is_generator={:?} places={:?}", def_id, is_generator, places ); - if let Some((args_span, generator_kind, var_span)) = self.closure_span( + if let Some((args_span, var_span)) = self.closure_span( *def_id, Place::from(target).as_ref(), places ) { return ClosureUse { - generator_kind, + is_generator, args_span, var_span, }; @@ -896,7 +884,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { def_id: DefId, target_place: PlaceRef<'cx, 'tcx>, places: &Vec>, - ) -> Option<(Span, Option, Span)> { + ) -> Option<(Span, Span)> { debug!( "closure_span: def_id={:?} target_place={:?} places={:?}", def_id, target_place, places @@ -905,16 +893,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind; debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr); if let hir::ExprKind::Closure( - .., body_id, args_span, _ + .., args_span, _ ) = expr { for (upvar, place) in self.infcx.tcx.upvars(def_id)?.values().zip(places) { match place { Operand::Copy(place) | Operand::Move(place) if target_place == place.as_ref() => { debug!("closure_span: found captured local {:?}", place); - let body = self.infcx.tcx.hir().body(*body_id); - let generator_kind = body.generator_kind(); - return Some((*args_span, generator_kind, upvar.span)); + return Some((*args_span, upvar.span)); }, _ => {} } diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index ce5d2a14bd122..1f17ab69f6660 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -5,7 +5,7 @@ use rustc::mir::{BasicBlock, Local, Location}; use rustc::ty::RegionVid; -use rustc_index::bit_set::BitIter; +use rustc_data_structures::bit_set::BitIter; use crate::borrow_check::location::LocationIndex; diff --git a/src/librustc_mir/borrow_check/location.rs b/src/librustc_mir/borrow_check/location.rs index 9e94317b87e54..cc44dc3f5d46b 100644 --- a/src/librustc_mir/borrow_check/location.rs +++ b/src/librustc_mir/borrow_check/location.rs @@ -1,5 +1,5 @@ use rustc::mir::{BasicBlock, Location, Body}; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; /// Maps between a MIR Location, which identifies a particular /// statement within a basic block, to a "rich location", which @@ -17,7 +17,7 @@ crate struct LocationTable { statements_before_block: IndexVec, } -rustc_index::newtype_index! { +newtype_index! { pub struct LocationIndex { DEBUG_FORMAT = "LocationIndex({})" } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index c3369e872151a..cf80a1bc6437e 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -18,10 +18,10 @@ use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt}; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use smallvec::SmallVec; use std::collections::BTreeMap; @@ -1133,12 +1133,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Special case: you can assign a immutable local variable // (e.g., `x = ...`) so long as it has never been initialized // before (at this point in the flow). - if let Some(local) = place_span.0.as_local() { - if let Mutability::Not = self.body.local_decls[local].mutability { + if let Place { + base: PlaceBase::Local(local), + projection: box [], + } = place_span.0 { + if let Mutability::Not = self.body.local_decls[*local].mutability { // check for reassignments to immutable local variables self.check_if_reassignment_to_immutable_state( location, - local, + *local, place_span, flow_state, ); @@ -1285,58 +1288,60 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // captures of a closure are copied/moved directly // when generating MIR. match *operand { - Operand::Move(ref place) | Operand::Copy(ref place) => { - match place.as_local() { - Some(local) 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. - return; - } - // This is an edge case where we have a `move` closure - // inside a non-move closure, and the inner closure - // contains a mutation: - // - // let mut i = 0; - // || { move || { i += 1; }; }; - // - // In this case our usual strategy of assuming that the - // variable will be captured by mutable reference is - // wrong, since `i` can be copied into the inner - // closure from a shared reference. - // - // As such we have to search for the local that this - // capture comes from and mark it as being used as mut. - - let temp_mpi = self.move_data.rev_lookup.find_local(local); - let init = if let [init_index] = *self.move_data.init_path_map[temp_mpi] { - &self.move_data.inits[init_index] - } else { - bug!("temporary should be initialized exactly once") - }; - - let loc = match init.location { - InitLocation::Statement(stmt) => stmt, - _ => bug!("temporary initialized in arguments"), - }; - - let bbd = &self.body[loc.block]; - let stmt = &bbd.statements[loc.statement_index]; - debug!("temporary assigned in: stmt={:?}", stmt); - - 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 \ - or references to user variables" - ); - } - } - _ => propagate_closure_used_mut_place(self, place), + Operand::Move(Place { + base: PlaceBase::Local(local), + projection: box [], + }) | + Operand::Copy(Place { + base: PlaceBase::Local(local), + 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. + return; + } + // This is an edge case where we have a `move` closure + // inside a non-move closure, and the inner closure + // contains a mutation: + // + // let mut i = 0; + // || { move || { i += 1; }; }; + // + // In this case our usual strategy of assuming that the + // variable will be captured by mutable reference is + // wrong, since `i` can be copied into the inner + // closure from a shared reference. + // + // As such we have to search for the local that this + // capture comes from and mark it as being used as mut. + + let temp_mpi = self.move_data.rev_lookup.find_local(local); + let init = if let [init_index] = *self.move_data.init_path_map[temp_mpi] { + &self.move_data.inits[init_index] + } else { + bug!("temporary should be initialized exactly once") + }; + + let loc = match init.location { + InitLocation::Statement(stmt) => stmt, + _ => bug!("temporary initialized in arguments"), + }; + + let bbd = &self.body[loc.block]; + let stmt = &bbd.statements[loc.statement_index]; + debug!("temporary assigned in: stmt={:?}", stmt); + + 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 \ + or references to user variables"); } } + Operand::Move(ref place) + | Operand::Copy(ref place) => { + propagate_closure_used_mut_place(self, place); + } Operand::Constant(..) => {} } } @@ -1697,7 +1702,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("check_if_assigned_path_is_moved place: {:?}", place); // None case => assigning to `x` does not require `x` be initialized. - let mut cursor = &*place.projection.as_ref(); + let mut cursor = &*place.projection; while let [proj_base @ .., elem] = cursor { cursor = proj_base; @@ -1939,16 +1944,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.is_mutable(place.as_ref(), is_local_mutation_allowed), self.errors_buffer.is_empty() ) { - // rust-lang/rust#46908: In pure NLL mode this code path should be - // unreachable, but we use `delay_span_bug` because we can hit this when - // dereferencing a non-Copy raw pointer *and* have `-Ztreat-err-as-bug` - // enabled. We don't want to ICE for that case, as other errors will have - // been emitted (#52262). - self.infcx.tcx.sess.delay_span_bug(span, &format!( + // rust-lang/rust#46908: In pure NLL mode this code path should + // be unreachable (and thus we signal an ICE in the else branch here). + span_bug!( + span, "Accessing `{:?}` with the kind `{:?}` shouldn't be possible", place, kind, - )); + ); } return false; } diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index d9e958d945001..bf5bddadd16f1 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -89,41 +89,45 @@ 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( - box(place, 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) .map(|stmt| &stmt.kind) { - if let Some(local) = place.as_local() { - let local_decl = &self.body.local_decls[local]; - // opt_match_place is the - // match_span is the span of the expression being matched on - // match *x.y { ... } match_place is Some(*x.y) - // ^^^^ match_span is the span of *x.y - // - // opt_match_place is None for let [mut] x = ... statements, - // whether or not the right-hand side is a place expression - if let Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { - opt_match_place: Some((ref opt_match_place, match_span)), - binding_mode: _, - opt_ty_info: _, - pat_span: _, - }))) = local_decl.is_user_variable - { - let stmt_source_info = self.body.source_info(location); - self.append_binding_error( - grouped_errors, - kind, - original_path, - move_from, - local, - opt_match_place, - match_span, - stmt_source_info.span, - ); - return; - } + let local_decl = &self.body.local_decls[*local]; + // opt_match_place is the + // match_span is the span of the expression being matched on + // match *x.y { ... } match_place is Some(*x.y) + // ^^^^ match_span is the span of *x.y + // + // opt_match_place is None for let [mut] x = ... statements, + // whether or not the right-hand side is a place expression + if let Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + opt_match_place: Some((ref opt_match_place, match_span)), + binding_mode: _, + opt_ty_info: _, + pat_span: _, + }))) = local_decl.is_user_variable + { + let stmt_source_info = self.body.source_info(location); + self.append_binding_error( + grouped_errors, + kind, + original_path, + move_from, + *local, + opt_match_place, + match_span, + stmt_source_info.span, + ); + return; } } @@ -303,11 +307,11 @@ 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.as_ref() { - &[ref proj_base @ .., ProjectionElem::Deref] => { + let deref_base = match &deref_target_place.projection { + box [proj_base @ .., ProjectionElem::Deref] => { PlaceRef { base: &deref_target_place.base, - projection: &proj_base, + projection: proj_base, } } _ => bug!("deref_target_place is not a deref projection"), @@ -337,8 +341,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ty::Closure(def_id, closure_substs) if def_id == self.mir_def_id && upvar_field.is_some() => { - let closure_kind_ty = closure_substs - .as_closure().kind_ty(def_id, self.infcx.tcx); + let closure_kind_ty = closure_substs.closure_kind_ty(def_id, self.infcx.tcx); let closure_kind = closure_kind_ty.to_opt_closure_kind(); let capture_description = match closure_kind { Some(ty::ClosureKind::Fn) => { diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 68b33331a1ffb..d6b91373ab825 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -5,7 +5,7 @@ use rustc::mir::{ Mutability, Place, PlaceRef, PlaceBase, ProjectionElem, Static, StaticKind }; use rustc::ty::{self, Ty, TyCtxt}; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use syntax_pos::Span; use syntax_pos::symbol::kw; @@ -49,7 +49,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [], } => { item_msg = format!("`{}`", access_place_desc.unwrap()); - if access_place.as_local().is_some() { + if let Place { + base: PlaceBase::Local(_), + projection: box [], + } = access_place { reason = ", as it is not declared as mutable".to_string(); } else { let name = self.body.local_decls[*local] @@ -150,10 +153,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }), projection: [], } => { - if let PlaceRef { - base: &PlaceBase::Static(_), - projection: &[], - } = access_place.as_ref() { + if let Place { + base: PlaceBase::Static(_), + projection: box [], + } = access_place { item_msg = format!("immutable static item `{}`", access_place_desc.unwrap()); reason = String::new(); } else { diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index cae303039a194..1e5f613aedc23 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -8,11 +8,11 @@ use rustc::infer::InferCtxt; use rustc::mir::visit::TyContext; use rustc::mir::visit::Visitor; use rustc::mir::{ - BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, PlaceRef, 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, RegionVid, Ty}; +use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty}; use rustc::ty::subst::SubstsRef; pub(super) fn generate_constraints<'cx, 'tcx>( @@ -91,6 +91,20 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> { self.super_ty(ty); } + /// We sometimes have `generator_substs` within an rvalue, or within a + /// call. Make them live at the location where they appear. + fn visit_generator_substs(&mut self, substs: &GeneratorSubsts<'tcx>, location: Location) { + self.add_regular_live_constraint(*substs, location); + self.super_generator_substs(substs); + } + + /// We sometimes have `closure_substs` within an rvalue, or within a + /// call. Make them live at the location where they appear. + fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, location: Location) { + self.add_regular_live_constraint(*substs, location); + self.super_closure_substs(substs); + } + fn visit_statement( &mut self, statement: &Statement<'tcx>, @@ -211,14 +225,14 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> { // - if it's a deeper projection, we have to filter which // of the borrows are killed: the ones whose `borrowed_place` // conflicts with the `place`. - match place.as_ref() { - PlaceRef { - base: &PlaceBase::Local(local), - projection: &[], + match place { + Place { + base: PlaceBase::Local(local), + projection: box [], } | - PlaceRef { - base: &PlaceBase::Local(local), - projection: &[ProjectionElem::Deref], + Place { + base: PlaceBase::Local(local), + projection: box [ProjectionElem::Deref], } => { debug!( "Recording `killed` facts for borrows of local={:?} at location={:?}", @@ -229,21 +243,21 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> { all_facts, self.borrow_set, self.location_table, - &local, + local, location, ); } - PlaceRef { - base: &PlaceBase::Static(_), + Place { + base: PlaceBase::Static(_), .. } => { // Ignore kills of static or static mut variables. } - PlaceRef { - base: &PlaceBase::Local(local), - projection: &[.., _], + Place { + base: PlaceBase::Local(local), + projection: box [.., _], } => { // Kill conflicting borrows of the innermost local. debug!( @@ -252,7 +266,7 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> { local, location ); - if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) { + if let Some(borrow_indices) = self.borrow_set.local_map.get(local) { for &borrow_index in borrow_indices { let places_conflict = places_conflict::places_conflict( self.infcx.tcx, diff --git a/src/librustc_mir/borrow_check/nll/constraints/graph.rs b/src/librustc_mir/borrow_check/nll/constraints/graph.rs index b6a9a7ee6578f..b5630251e5830 100644 --- a/src/librustc_mir/borrow_check/nll/constraints/graph.rs +++ b/src/librustc_mir/borrow_check/nll/constraints/graph.rs @@ -4,7 +4,7 @@ use crate::borrow_check::nll::constraints::{OutlivesConstraintSet, OutlivesConst use rustc::mir::ConstraintCategory; use rustc::ty::RegionVid; use rustc_data_structures::graph; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use syntax_pos::DUMMY_SP; /// The construct graph organizes the constraints by their end-points. diff --git a/src/librustc_mir/borrow_check/nll/constraints/mod.rs b/src/librustc_mir/borrow_check/nll/constraints/mod.rs index 8a242b7ee25ba..6121ed0cf0d1c 100644 --- a/src/librustc_mir/borrow_check/nll/constraints/mod.rs +++ b/src/librustc_mir/borrow_check/nll/constraints/mod.rs @@ -2,7 +2,7 @@ use crate::borrow_check::nll::type_check::Locations; use rustc::mir::ConstraintCategory; use rustc::ty::RegionVid; use rustc_data_structures::graph::scc::Sccs; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use std::fmt; use std::ops::Index; @@ -71,7 +71,7 @@ impl Index for OutlivesConstraintSet { } } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct OutlivesConstraint { // NB. The ordering here is not significant for correctness, but // it is for convenience. Before we dump the constraints in the @@ -100,13 +100,13 @@ impl fmt::Debug for OutlivesConstraint { } } -rustc_index::newtype_index! { +newtype_index! { pub struct OutlivesConstraintIndex { DEBUG_FORMAT = "OutlivesConstraintIndex({})" } } -rustc_index::newtype_index! { +newtype_index! { pub struct ConstraintSccIndex { DEBUG_FORMAT = "ConstraintSccIndex({})" } 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 26bead3047d5d..ff4243df6e9b8 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -6,8 +6,8 @@ use crate::borrow_check::nll::region_infer::{Cause, RegionName}; use crate::borrow_check::nll::ConstraintDescription; use crate::borrow_check::{MirBorrowckCtxt, WriteKind}; use rustc::mir::{ - CastKind, ConstraintCategory, FakeReadCause, Local, Location, Body, Operand, Place, Rvalue, - Statement, StatementKind, TerminatorKind, + CastKind, ConstraintCategory, FakeReadCause, Local, Location, Body, Operand, Place, PlaceBase, + Rvalue, Statement, StatementKind, TerminatorKind, }; use rustc::ty::{self, TyCtxt}; use rustc::ty::adjustment::{PointerCast}; @@ -17,7 +17,6 @@ use syntax_pos::Span; mod find_use; -#[derive(Debug)] pub(in crate::borrow_check) enum BorrowExplanation { UsedLater(LaterUseKind, Span), UsedLaterInLoop(LaterUseKind, Span), @@ -36,7 +35,7 @@ pub(in crate::borrow_check) enum BorrowExplanation { Unexplained, } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy)] pub(in crate::borrow_check) enum LaterUseKind { TraitCapture, ClosureCapture, @@ -273,9 +272,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut should_note_order = false; if body.local_decls[local].name.is_some() { if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place { - if let Some(borrowed_local) = place.as_local() { - if body.local_decls[borrowed_local].name.is_some() - && local != borrowed_local + if let Place { + base: PlaceBase::Local(borrowed_local), + projection: box [], + } = place { + if body.local_decls[*borrowed_local].name.is_some() + && local != *borrowed_local { should_note_order = true; } @@ -455,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.dominators) + target.dominates(source, &self.body.dominators()) } /// Determine how the borrow was later used. @@ -491,19 +493,22 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Just point to the function, to reduce the chance of overlapping spans. let function_span = match func { Operand::Constant(c) => c.span, - Operand::Copy(place) | - Operand::Move(place) => { - if let Some(l) = place.as_local() { - let local_decl = &self.body.local_decls[l]; - if local_decl.name.is_none() { - local_decl.source_info.span - } else { - span - } + Operand::Copy(Place { + base: PlaceBase::Local(l), + projection: box [], + }) | + Operand::Move(Place { + base: PlaceBase::Local(l), + projection: box [], + }) => { + let local_decl = &self.body.local_decls[*l]; + if local_decl.name.is_none() { + local_decl.source_info.span } else { span } } + _ => span, }; return (LaterUseKind::Call, function_span); } else { @@ -536,14 +541,14 @@ 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(box(ref place, _)), + kind: StatementKind::Assign(box(Place { + base: PlaceBase::Local(local), + projection: box [], + }, _)), .. - }) = stmt { - if let Some(local) = place.as_local() { - local - } else { - return false; - } + }) = stmt + { + local } else { return false; }; @@ -576,13 +581,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // If we see a use, we should check whether it is our data, and if so // update the place that we're looking for to that new place. Rvalue::Use(operand) => match operand { - Operand::Copy(place) - | Operand::Move(place) => { - if let Some(from) = place.as_local() { - if from == target { - target = into; - } - } + Operand::Copy(Place { + base: PlaceBase::Local(from), + projection: box [], + }) + | Operand::Move(Place { + base: PlaceBase::Local(from), + projection: box [], + }) + if *from == target => + { + target = into; } _ => {} }, @@ -591,25 +600,28 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Rvalue::Cast( CastKind::Pointer(PointerCast::Unsize), operand, ty ) => match operand { - Operand::Copy(place) - | Operand::Move(place) => { - if let Some(from) = place.as_local() { - if from == target { - debug!("was_captured_by_trait_object: ty={:?}", ty); - // Check the type for a trait object. - return match ty.kind { - // `&dyn Trait` - ty::Ref(_, ty, _) if ty.is_trait() => true, - // `Box` - _ if ty.is_box() && ty.boxed_ty().is_trait() => true, - // `dyn Trait` - _ if ty.is_trait() => true, - // Anything else. - _ => false, - }; - } - } - return false; + Operand::Copy(Place { + base: PlaceBase::Local(from), + projection: box [], + }) + | Operand::Move(Place { + base: PlaceBase::Local(from), + projection: box [], + }) + if *from == target => + { + debug!("was_captured_by_trait_object: ty={:?}", ty); + // Check the type for a trait object. + return match ty.kind { + // `&dyn Trait` + ty::Ref(_, ty, _) if ty.is_trait() => true, + // `Box` + _ if ty.is_box() && ty.boxed_ty().is_trait() => true, + // `dyn Trait` + _ if ty.is_trait() => true, + // Anything else. + _ => false, + }; } _ => return false, }, @@ -625,33 +637,34 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("was_captured_by_trait_object: terminator={:?}", terminator); if let TerminatorKind::Call { - destination: Some((place, block)), + destination: Some((Place { + base: PlaceBase::Local(dest), + projection: box [], + }, block)), args, .. - } = &terminator.kind { - if let Some(dest) = place.as_local() { - debug!( - "was_captured_by_trait_object: target={:?} dest={:?} args={:?}", - target, dest, args - ); - // Check if one of the arguments to this function is the target place. - let found_target = args.iter().any(|arg| { - if let Operand::Move(place) = arg { - if let Some(potential) = place.as_local() { - potential == target - } else { - false - } - } else { - false - } - }); - - // If it is, follow this to the next block and update the target. - if found_target { - target = dest; - queue.push(block.start_location()); + } = &terminator.kind + { + debug!( + "was_captured_by_trait_object: target={:?} dest={:?} args={:?}", + target, dest, args + ); + // Check if one of the arguments to this function is the target place. + let found_target = args.iter().any(|arg| { + if let Operand::Move(Place { + base: PlaceBase::Local(potential), + projection: box [], + }) = arg { + *potential == target + } else { + false } + }); + + // If it is, follow this to the next block and update the target. + if found_target { + target = *dest; + queue.push(block.start_location()); } } } diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index 13e5769c5bea8..f0beb4d3ae32d 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -4,7 +4,7 @@ use polonius_engine::AllFacts as PoloniusAllFacts; use polonius_engine::Atom; use rustc::mir::Local; use rustc::ty::{RegionVid, TyCtxt}; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use std::error::Error; use std::fmt::Debug; use std::fs::{self, File}; diff --git a/src/librustc_mir/borrow_check/nll/member_constraints.rs b/src/librustc_mir/borrow_check/nll/member_constraints.rs index 75213d30982f9..b5e2e111f38e5 100644 --- a/src/librustc_mir/borrow_check/nll/member_constraints.rs +++ b/src/librustc_mir/borrow_check/nll/member_constraints.rs @@ -2,7 +2,7 @@ use crate::rustc::ty::{self, Ty}; use rustc::hir::def_id::DefId; use rustc::infer::region_constraints::MemberConstraint; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use std::hash::Hash; use std::ops::Index; use syntax_pos::Span; @@ -11,7 +11,7 @@ use syntax_pos::Span; /// indexed by the region `R0`. crate struct MemberConstraintSet<'tcx, R> where - R: Copy + Eq, + R: Copy + Hash + Eq, { /// Stores the first "member" constraint for a given `R0`. This is an /// index into the `constraints` vector below. @@ -51,7 +51,7 @@ crate struct NllMemberConstraint<'tcx> { end_index: usize, } -rustc_index::newtype_index! { +newtype_index! { crate struct NllMemberConstraintIndex { DEBUG_FORMAT = "MemberConstraintIndex({})" } @@ -191,7 +191,7 @@ where impl<'tcx, R> Index for MemberConstraintSet<'tcx, R> where - R: Copy + Eq, + R: Copy + Hash + Eq, { type Output = NllMemberConstraint<'tcx>; diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index b2e5751b902e7..1ff3228afa376 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -14,7 +14,7 @@ use rustc::infer::InferCtxt; use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Location, Body, LocalKind, BasicBlock, Promoted}; use rustc::ty::{self, RegionKind, RegionVid}; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::Diagnostic; use std::fmt::Debug; use std::env; 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 7362ae9c638b1..e29e9232012bc 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 @@ -1,4 +1,5 @@ use crate::borrow_check::nll::constraints::OutlivesConstraint; +use crate::borrow_check::nll::region_infer::AppliedMemberConstraint; use crate::borrow_check::nll::region_infer::RegionInferenceContext; use crate::borrow_check::nll::type_check::Locations; use crate::borrow_check::nll::universal_regions::DefiningTy; @@ -11,7 +12,7 @@ use rustc::infer::InferCtxt; use rustc::infer::NLLRegionVariableOrigin; use rustc::mir::{ConstraintCategory, Location, Body}; use rustc::ty::{self, RegionVid}; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::DiagnosticBuilder; use std::collections::VecDeque; use syntax::errors::Applicability; @@ -97,11 +98,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, body: &Body<'tcx>, from_region: RegionVid, - from_region_origin: NLLRegionVariableOrigin, target_test: impl Fn(RegionVid) -> bool, ) -> (ConstraintCategory, bool, Span) { - debug!("best_blame_constraint(from_region={:?}, from_region_origin={:?})", - from_region, from_region_origin); + debug!("best_blame_constraint(from_region={:?})", from_region); // Find all paths let (path, target_region) = @@ -154,85 +153,19 @@ impl<'tcx> RegionInferenceContext<'tcx> { // we still want to screen for an "interesting" point to // highlight (e.g., a call site or something). let target_scc = self.constraint_sccs.scc(target_region); - let mut range = 0..path.len(); - - // As noted above, when reporting an error, there is typically a chain of constraints - // leading from some "source" region which must outlive some "target" region. - // In most cases, we prefer to "blame" the constraints closer to the target -- - // but there is one exception. When constraints arise from higher-ranked subtyping, - // we generally prefer to blame the source value, - // as the "target" in this case tends to be some type annotation that the user gave. - // Therefore, if we find that the region origin is some instantiation - // of a higher-ranked region, we start our search from the "source" point - // rather than the "target", and we also tweak a few other things. - // - // An example might be this bit of Rust code: - // - // ```rust - // let x: fn(&'static ()) = |_| {}; - // let y: for<'a> fn(&'a ()) = x; - // ``` - // - // In MIR, this will be converted into a combination of assignments and type ascriptions. - // In particular, the 'static is imposed through a type ascription: - // - // ```rust - // x = ...; - // AscribeUserType(x, fn(&'static ()) - // y = x; - // ``` - // - // We wind up ultimately with constraints like - // - // ```rust - // !a: 'temp1 // from the `y = x` statement - // 'temp1: 'temp2 - // 'temp2: 'static // from the AscribeUserType - // ``` - // - // and here we prefer to blame the source (the y = x statement). - let blame_source = match from_region_origin { - NLLRegionVariableOrigin::FreeRegion - | NLLRegionVariableOrigin::Existential { from_forall: false } => { - true - } - NLLRegionVariableOrigin::Placeholder(_) - | NLLRegionVariableOrigin::Existential { from_forall: true } => { - false - } - }; - - let find_region = |i: &usize| { - let constraint = path[*i]; + let best_choice = (0..path.len()).rev().find(|&i| { + let constraint = path[i]; let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup); - if blame_source { - match categorized_path[*i].0 { - ConstraintCategory::OpaqueType | ConstraintCategory::Boring | - ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal => false, - ConstraintCategory::TypeAnnotation | ConstraintCategory::Return | - ConstraintCategory::Yield => true, - _ => constraint_sup_scc != target_scc, - } - } else { - match categorized_path[*i].0 { - ConstraintCategory::OpaqueType | ConstraintCategory::Boring | - ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal => false, - _ => true - } + match categorized_path[i].0 { + ConstraintCategory::OpaqueType | ConstraintCategory::Boring | + ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal => false, + ConstraintCategory::TypeAnnotation | ConstraintCategory::Return | + ConstraintCategory::Yield => true, + _ => constraint_sup_scc != target_scc, } - }; - - let best_choice = if blame_source { - range.rev().find(find_region) - } else { - range.find(find_region) - }; - - debug!("best_blame_constraint: best_choice={:?} blame_source={}", - best_choice, blame_source); - + }); if let Some(i) = best_choice { if let Some(next) = categorized_path.get(i + 1) { if categorized_path[i].0 == ConstraintCategory::Return @@ -320,33 +253,29 @@ impl<'tcx> RegionInferenceContext<'tcx> { let outgoing_edges_from_graph = self.constraint_graph .outgoing_edges(r, &self.constraints, fr_static); - // Always inline this closure because it can be hot. - let mut handle_constraint = #[inline(always)] |constraint: OutlivesConstraint| { + + // But member constraints can also give rise to `'r: 'x` + // edges that were not part of the graph initially, so + // watch out for those. + let outgoing_edges_from_picks = self.applied_member_constraints(r) + .iter() + .map(|&AppliedMemberConstraint { min_choice, member_constraint_index, .. }| { + let p_c = &self.member_constraints[member_constraint_index]; + OutlivesConstraint { + sup: r, + sub: min_choice, + locations: Locations::All(p_c.definition_span), + category: ConstraintCategory::OpaqueType, + } + }); + + for constraint in outgoing_edges_from_graph.chain(outgoing_edges_from_picks) { debug_assert_eq!(constraint.sup, r); let sub_region = constraint.sub; if let Trace::NotVisited = context[sub_region] { context[sub_region] = Trace::FromOutlivesConstraint(constraint); deque.push_back(sub_region); } - }; - - // This loop can be hot. - for constraint in outgoing_edges_from_graph { - handle_constraint(constraint); - } - - // Member constraints can also give rise to `'r: 'x` edges that - // were not part of the graph initially, so watch out for those. - // (But they are extremely rare; this loop is very cold.) - for constraint in self.applied_member_constraints(r) { - let p_c = &self.member_constraints[constraint.member_constraint_index]; - let constraint = OutlivesConstraint { - sup: r, - sub: constraint.min_choice, - locations: Locations::All(p_c.definition_span), - category: ConstraintCategory::OpaqueType, - }; - handle_constraint(constraint); } } @@ -368,13 +297,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, mir_def_id: DefId, fr: RegionVid, - fr_origin: NLLRegionVariableOrigin, outlived_fr: RegionVid, renctx: &mut RegionErrorNamingCtx, ) -> DiagnosticBuilder<'a> { debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); - let (category, _, span) = self.best_blame_constraint(body, fr, fr_origin, |r| { + let (category, _, span) = self.best_blame_constraint(body, fr, |r| { self.provides_universal_region(r, fr, outlived_fr) }); @@ -781,7 +709,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { let (category, from_closure, span) = self.best_blame_constraint( body, borrow_region, - NLLRegionVariableOrigin::FreeRegion, |r| self.provides_universal_region(r, borrow_region, outlived_region) ); @@ -841,13 +768,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, body: &Body<'tcx>, fr1: RegionVid, - fr1_origin: NLLRegionVariableOrigin, fr2: RegionVid, ) -> (ConstraintCategory, Span) { let (category, _, span) = self.best_blame_constraint( body, fr1, - fr1_origin, |r| self.provides_universal_region(r, fr1, fr2), ); (category, span) @@ -875,7 +800,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) { if let ty::BoundRegion::BrEnv = free_region.bound_region { if let DefiningTy::Closure(def_id, substs) = self.universal_regions.defining_ty { - let closure_kind_ty = substs.as_closure().kind_ty(def_id, infcx.tcx); + let closure_kind_ty = substs.closure_kind_ty(def_id, infcx.tcx); return Some(ty::ClosureKind::FnMut) == closure_kind_ty.to_opt_closure_kind(); } } @@ -900,9 +825,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { universe1.cannot_name(placeholder.universe) } - NLLRegionVariableOrigin::FreeRegion | NLLRegionVariableOrigin::Existential { .. } => { - false - } + NLLRegionVariableOrigin::FreeRegion | NLLRegionVariableOrigin::Existential => false, } } } 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 d6e84940291a5..c4b508e030f39 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 @@ -18,14 +18,14 @@ use rustc::ty::print::RegionHighlightMode; use rustc_errors::DiagnosticBuilder; use syntax::symbol::kw; use rustc_data_structures::fx::FxHashMap; -use syntax_pos::{Span, symbol::Symbol}; +use syntax_pos::{Span, symbol::InternedString}; /// 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: Symbol, + crate name: InternedString, /// Where the region comes from. crate source: RegionNameSource, } @@ -109,7 +109,7 @@ impl RegionName { } #[allow(dead_code)] - crate fn name(&self) -> Symbol { + crate fn name(&self) -> InternedString { self.name } @@ -273,7 +273,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } ty::ReStatic => Some(RegionName { - name: kw::StaticLifetime, + name: kw::StaticLifetime.as_interned_str(), source: RegionNameSource::Static }), @@ -300,7 +300,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }; let region_name = self.synthesize_region_name(renctx); - let closure_kind_ty = substs.as_closure().kind_ty(def_id, tcx); + let closure_kind_ty = substs.closure_kind_ty(def_id, tcx); let note = match closure_kind_ty.to_opt_closure_kind() { Some(ty::ClosureKind::Fn) => { "closure implements `Fn`, so references to captured variables \ @@ -360,7 +360,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, tcx: TyCtxt<'tcx>, error_region: &RegionKind, - name: Symbol, + name: InternedString, ) -> Span { let scope = error_region.free_region_binding_scope(tcx); let node = tcx.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID); @@ -399,6 +399,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.universal_regions.unnormalized_input_tys[implicit_inputs + argument_index]; if let Some(region_name) = self.give_name_if_we_can_match_hir_ty_from_argument( infcx, + body, mir_def_id, fr, arg_ty, @@ -414,6 +415,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn give_name_if_we_can_match_hir_ty_from_argument( &self, infcx: &InferCtxt<'_, 'tcx>, + body: &Body<'tcx>, mir_def_id: DefId, needle_fr: RegionVid, argument_ty: Ty<'tcx>, @@ -422,14 +424,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) -> 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)?; - let argument_hir_ty: &hir::Ty = fn_decl.inputs.get(argument_index)?; + let argument_hir_ty: &hir::Ty = &fn_decl.inputs[argument_index]; match argument_hir_ty.kind { // This indicates a variable with no type annotation, like // `|x|`... in that case, we can't highlight the type but // must highlight the variable. - // NOTE(eddyb) this is handled in/by the sole caller - // (`give_name_if_anonymous_region_appears_in_arguments`). - hir::TyKind::Infer => None, + hir::TyKind::Infer => self.give_name_if_we_cannot_match_hir_ty( + infcx, + body, + needle_fr, + argument_ty, + renctx, + ), _ => self.give_name_if_we_can_match_hir_ty( infcx.tcx, @@ -837,10 +843,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { } /// Creates a synthetic region named `'1`, incrementing the counter. - fn synthesize_region_name(&self, renctx: &mut RegionErrorNamingCtx) -> Symbol { + fn synthesize_region_name(&self, renctx: &mut RegionErrorNamingCtx) -> InternedString { let c = renctx.counter; renctx.counter += 1; - Symbol::intern(&format!("'{:?}", c)) + InternedString::intern(&format!("'{:?}", c)) } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs index 7f0e97c9ae426..750a1324faeb3 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs @@ -3,7 +3,7 @@ use crate::borrow_check::nll::ToRegionVid; use crate::borrow_check::Upvar; use rustc::mir::{Local, Body}; use rustc::ty::{RegionVid, TyCtxt}; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use syntax::source_map::Span; use syntax_pos::symbol::Symbol; 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 dbb810db555b4..78e7943598d68 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -27,12 +27,12 @@ use rustc::mir::{ use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable}; use rustc::util::common::ErrorReported; use rustc_data_structures::binary_search_util; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::WithSuccessors; use rustc_data_structures::graph::scc::Sccs; use rustc_data_structures::graph::vec_graph::VecGraph; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::{Diagnostic, DiagnosticBuilder}; use syntax_pos::Span; @@ -406,7 +406,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - NLLRegionVariableOrigin::Existential { .. } => { + NLLRegionVariableOrigin::Existential => { // For existential, regions, nothing to do. } } @@ -1348,7 +1348,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.check_bound_universal_region(infcx, body, mir_def_id, fr, placeholder); } - NLLRegionVariableOrigin::Existential { .. } => { + NLLRegionVariableOrigin::Existential => { // nothing to check here } } @@ -1461,8 +1461,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!("check_universal_region: fr_minus={:?}", fr_minus); let blame_span_category = - self.find_outlives_blame_span(body, longer_fr, - NLLRegionVariableOrigin::FreeRegion,shorter_fr); + self.find_outlives_blame_span(body, longer_fr, shorter_fr); // Grow `shorter_fr` until we find some non-local regions. (We // always will.) We'll call them `shorter_fr+` -- they're ever @@ -1495,7 +1494,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { infcx, mir_def_id, longer_fr, - NLLRegionVariableOrigin::FreeRegion, shorter_fr, region_naming, ); @@ -1549,9 +1547,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }; // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. - let (_, span) = self.find_outlives_blame_span( - body, longer_fr, NLLRegionVariableOrigin::Placeholder(placeholder), error_region - ); + let (_, span) = self.find_outlives_blame_span(body, longer_fr, error_region); // Obviously, this error message is far from satisfactory. // At present, though, it only appears in unit tests -- @@ -1612,7 +1608,7 @@ impl<'tcx> RegionDefinition<'tcx> { let origin = match rv_origin { RegionVariableOrigin::NLL(origin) => origin, - _ => NLLRegionVariableOrigin::Existential { from_forall: false }, + _ => NLLRegionVariableOrigin::Existential, }; Self { origin, universe, external_name: None } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index 7a86536573dcf..6f9f5707935ba 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -1,9 +1,9 @@ use rustc::mir::{BasicBlock, Location, Body}; use rustc::ty::{self, RegionVid}; -use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix}; +use rustc_data_structures::bit_set::{HybridBitSet, SparseBitMatrix}; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::Idx; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::indexed_vec::IndexVec; use std::fmt::Debug; use std::rc::Rc; @@ -116,20 +116,20 @@ impl RegionValueElements { } } -rustc_index::newtype_index! { +newtype_index! { /// A single integer representing a `Location` in the MIR control-flow /// graph. Constructed efficiently from `RegionValueElements`. pub struct PointIndex { DEBUG_FORMAT = "PointIndex({})" } } -rustc_index::newtype_index! { +newtype_index! { /// A single integer representing a `ty::Placeholder`. pub struct PlaceholderIndex { DEBUG_FORMAT = "PlaceholderIndex({})" } } /// An individual element in a region value -- the value of a /// particular region variable consists of a set of these elements. -#[derive(Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] crate enum RegionElement { /// A point in the control-flow graph. Location(Location), diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index d949c7e01aab7..c479c38f30c7e 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,9 +1,9 @@ use rustc::ty::subst::SubstsRef; -use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::mir::{Body, Location, PlaceElem, Promoted}; +use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable}; +use rustc::mir::{Location, Body, Promoted}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; -use rustc_index::vec::IndexVec; +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. @@ -35,7 +35,7 @@ where infcx .tcx .fold_regions(value, &mut false, |_region, _depth| { - let origin = NLLRegionVariableOrigin::Existential { from_forall: false }; + let origin = NLLRegionVariableOrigin::Existential; infcx.next_nll_region_var(origin) }) } @@ -54,10 +54,6 @@ impl<'a, 'tcx> NLLVisitor<'a, 'tcx> { } impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) { debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context); @@ -66,21 +62,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { debug!("visit_ty: ty={:?}", ty); } - fn process_projection_elem( - &mut self, - elem: &PlaceElem<'tcx>, - ) -> Option> { - if let PlaceElem::Field(field, ty) = elem { - let new_ty = self.renumber_regions(ty); - - if new_ty != *ty { - return Some(PlaceElem::Field(*field, new_ty)); - } - } - - None - } - fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { debug!("visit_substs(substs={:?}, location={:?})", substs, location); @@ -101,4 +82,30 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _location: Location) { *constant = self.renumber_regions(&*constant); } + + fn visit_generator_substs(&mut self, + substs: &mut GeneratorSubsts<'tcx>, + location: Location) { + debug!( + "visit_generator_substs(substs={:?}, location={:?})", + substs, + location, + ); + + *substs = self.renumber_regions(substs); + + debug!("visit_generator_substs: substs={:?}", substs); + } + + fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) { + debug!( + "visit_closure_substs(substs={:?}, location={:?})", + substs, + location + ); + + *substs = self.renumber_regions(substs); + + debug!("visit_closure_substs: substs={:?}", substs); + } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs index 34ac96beb5ca3..c88f1cac35040 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs @@ -178,9 +178,6 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<' a: ty::Region<'tcx>, b: ty::Region<'tcx>, ) { - if let ty::ReEmpty = a { - return; - } let b = self.to_region_vid(b); let a = self.to_region_vid(a); self.add_outlives(b, a); @@ -193,9 +190,6 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<' a: ty::Region<'tcx>, bound: VerifyBound<'tcx>, ) { - if let ty::ReEmpty = a { - return; - } let type_test = self.verify_to_type_test(kind, a, bound); self.add_type_test(type_test); } diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs index d74dd0fc0f5f1..99661b1f7370a 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs @@ -12,7 +12,7 @@ use rustc::infer::LateBoundRegionConversionTime; use rustc::mir::*; use rustc::ty::Ty; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use syntax_pos::Span; use super::{Locations, TypeChecker}; 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 7dee00b3eca67..049d83bb22f1b 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 @@ -2,7 +2,7 @@ use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElem use crate::util::liveness::{categorize, DefUse}; use rustc::mir::visit::{PlaceContext, Visitor}; use rustc::mir::{Body, Local, Location}; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::vec_linked_list as vll; /// A map that cross references each local with the locations where it @@ -44,7 +44,7 @@ struct Appearance { next: Option, } -rustc_index::newtype_index! { +newtype_index! { pub struct AppearanceIndex { .. } } @@ -70,10 +70,6 @@ impl LocalUseMap { appearances: IndexVec::new(), }; - if live_locals.is_empty() { - return local_use_map; - } - 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); 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 a01b528833b2d..3f2ec1ba97017 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 @@ -36,39 +36,31 @@ pub(super) fn generate<'tcx>( ) { debug!("liveness::generate"); - let free_regions = regions_that_outlive_free_regions( - typeck.infcx.num_region_vars(), - &typeck.borrowck_context.universal_regions, - &typeck.borrowck_context.constraints.outlives_constraints, - ); - let live_locals = compute_live_locals(typeck.tcx(), &free_regions, body); - let facts_enabled = AllFacts::enabled(typeck.tcx()); - - - let polonius_drop_used = if facts_enabled { - let mut drop_used = Vec::new(); - polonius::populate_access_facts( - typeck, - body, - location_table, - move_data, - &mut drop_used, - ); - Some(drop_used) + let live_locals: Vec = if AllFacts::enabled(typeck.tcx()) { + // If "dump facts from NLL analysis" was requested perform + // the liveness analysis for all `Local`s. This case opens + // the possibility of the variables being analyzed in `trace` + // to be *any* `Local`, not just the "live" ones, so we can't + // make any assumptions past this point as to the characteristics + // of the `live_locals`. + // FIXME: Review "live" terminology past this point, we should + // not be naming the `Local`s as live. + body.local_decls.indices().collect() } else { - None + let free_regions = { + regions_that_outlive_free_regions( + typeck.infcx.num_region_vars(), + &typeck.borrowck_context.universal_regions, + &typeck.borrowck_context.constraints.outlives_constraints, + ) + }; + compute_live_locals(typeck.tcx(), &free_regions, body) }; - if !live_locals.is_empty() || facts_enabled { - trace::trace( - typeck, - body, - elements, - flow_inits, - move_data, - live_locals, - polonius_drop_used, - ); + if !live_locals.is_empty() { + trace::trace(typeck, body, elements, flow_inits, move_data, live_locals); + + 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 526ad7fb905bb..e37ddbda4be02 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 @@ -16,7 +16,7 @@ struct UseFactsExtractor<'me> { var_defined: &'me mut VarPointRelations, var_used: &'me mut VarPointRelations, location_table: &'me LocationTable, - var_drop_used: &'me mut Vec<(Local, Location)>, + var_drop_used: &'me mut VarPointRelations, move_data: &'me MoveData<'me>, path_accessed_at: &'me mut MovePathPointRelations, } @@ -39,7 +39,7 @@ impl UseFactsExtractor<'_> { fn insert_drop_use(&mut self, local: Local, location: Location) { debug!("LivenessFactsExtractor::insert_drop_use()"); - self.var_drop_used.push((local, location)); + self.var_drop_used.push((local, self.location_to_index(location))); } fn insert_path_access(&mut self, path: MovePathIndex, location: Location) { @@ -100,7 +100,6 @@ pub(super) fn populate_access_facts( body: &Body<'tcx>, location_table: &LocationTable, move_data: &MoveData<'_>, - drop_used: &mut Vec<(Local, Location)>, ) { debug!("populate_var_liveness_facts()"); @@ -108,16 +107,12 @@ pub(super) fn populate_access_facts( UseFactsExtractor { var_defined: &mut facts.var_defined, var_used: &mut facts.var_used, - var_drop_used: drop_used, + var_drop_used: &mut facts.var_drop_used, path_accessed_at: &mut facts.path_accessed_at, location_table, move_data, } .visit_body(body); - - facts.var_drop_used.extend(drop_used.iter().map(|&(local, location)| { - (local, location_table.mid_index(location)) - })); } for (local, local_decl) in body.local_decls.iter_enumerated() { 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 eacc4d084dbb8..9b55881cb1b10 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 @@ -12,8 +12,8 @@ use rustc::traits::query::dropck_outlives::DropckOutlivesResult; use rustc::traits::query::type_op::outlives::DropckOutlives; use rustc::traits::query::type_op::TypeOp; use rustc::ty::{Ty, TypeFoldable}; -use rustc_index::bit_set::HybridBitSet; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::bit_set::HybridBitSet; +use rustc_data_structures::fx::FxHashMap; use std::rc::Rc; /// This is the heart of the liveness computation. For each variable X @@ -37,7 +37,6 @@ pub(super) fn trace( flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>, move_data: &MoveData<'tcx>, live_locals: Vec, - polonius_drop_used: Option>, ) { debug!("trace()"); @@ -53,13 +52,7 @@ pub(super) fn trace( drop_data: FxHashMap::default(), }; - let mut results = LivenessResults::new(cx); - - if let Some(drop_used) = polonius_drop_used { - results.add_extra_drop_facts(drop_used, live_locals.iter().copied().collect()) - } - - results.compute_for_all_locals(live_locals); + LivenessResults::new(cx).compute_for_all_locals(live_locals); } /// Contextual state for the type-liveness generator. @@ -152,32 +145,6 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } - /// Add extra drop facts needed for Polonius. - /// - /// Add facts for all locals with free regions, since regions may outlive - /// the function body only at certain nodes in the CFG. - fn add_extra_drop_facts( - &mut self, - drop_used: Vec<(Local, Location)>, - live_locals: FxHashSet, - ) { - let locations = HybridBitSet::new_empty(self.cx.elements.num_points()); - - for (local, location) in drop_used { - if !live_locals.contains(&local) { - let local_ty = self.cx.body.local_decls[local].ty; - if local_ty.has_free_regions() { - self.cx.add_drop_live_facts_for( - local, - local_ty, - &[location], - &locations, - ); - } - } - } - } - /// Clear the value of fields that are "per local variable". fn reset_local_state(&mut self) { self.defs.clear(); 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 b5560fe6751bd..b981c76905c14 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -43,7 +43,7 @@ use rustc::ty::{ UserTypeAnnotationIndex, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_index::vec::{IndexVec, Idx}; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc::ty::layout::VariantIdx; use std::rc::Rc; use std::{fmt, iter, mem}; @@ -276,17 +276,7 @@ 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); - let ty = self.sanitize_type(constant, constant.literal.ty); - - self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| { - let live_region_vid = - self.cx.borrowck_context.universal_regions.to_region_vid(live_region); - self.cx - .borrowck_context - .constraints - .liveness_constraints - .add_element(live_region_vid, location); - }); + 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( @@ -480,13 +470,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { if place.projection.is_empty() { if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { - let is_promoted = match place.as_ref() { - PlaceRef { - base: &PlaceBase::Static(box Static { + let is_promoted = match place { + Place { + base: PlaceBase::Static(box Static { kind: StaticKind::Promoted(..), .. }), - projection: &[], + projection: box [], } => true, _ => false, }; @@ -538,37 +528,25 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let parent_body = mem::replace(&mut self.body, promoted_body); - // Use new sets of constraints and closure bounds so that we can - // modify their locations. let all_facts = &mut None; let mut constraints = Default::default(); let mut closure_bounds = Default::default(); - let mut liveness_constraints = LivenessValues::new( - Rc::new(RegionValueElements::new(promoted_body)), - ); // Don't try to add borrow_region facts for the promoted MIR + mem::swap(self.cx.borrowck_context.all_facts, all_facts); - let mut swap_constraints = |this: &mut Self| { - mem::swap(this.cx.borrowck_context.all_facts, all_facts); - mem::swap( - &mut this.cx.borrowck_context.constraints.outlives_constraints, - &mut constraints - ); - mem::swap( - &mut this.cx.borrowck_context.constraints.closure_bounds_mapping, - &mut closure_bounds - ); - mem::swap( - &mut this.cx.borrowck_context.constraints.liveness_constraints, - &mut liveness_constraints - ); - }; - - swap_constraints(self); + // Use a new sets of constraints and closure bounds so that we can + // modify their locations. + mem::swap( + &mut self.cx.borrowck_context.constraints.outlives_constraints, + &mut constraints + ); + mem::swap( + &mut self.cx.borrowck_context.constraints.closure_bounds_mapping, + &mut closure_bounds + ); self.visit_body(promoted_body); - if !self.errors_reported { // if verifier failed, don't do further checks to avoid ICEs self.cx.typeck_mir(promoted_body); @@ -576,15 +554,23 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { self.body = parent_body; // Merge the outlives constraints back in, at the given location. - swap_constraints(self); + mem::swap(self.cx.borrowck_context.all_facts, all_facts); + mem::swap( + &mut self.cx.borrowck_context.constraints.outlives_constraints, + &mut constraints + ); + mem::swap( + &mut self.cx.borrowck_context.constraints.closure_bounds_mapping, + &mut closure_bounds + ); let locations = location.to_locations(); for constraint in constraints.outlives().iter() { let mut constraint = *constraint; constraint.locations = locations; if let ConstraintCategory::Return - | ConstraintCategory::UseAsConst - | ConstraintCategory::UseAsStatic = constraint.category + | ConstraintCategory::UseAsConst + | ConstraintCategory::UseAsStatic = constraint.category { // "Returning" from a promoted is an assigment to a // temporary from the user's point of view. @@ -592,10 +578,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } self.cx.borrowck_context.constraints.outlives_constraints.push(constraint) } - for live_region in liveness_constraints.rows() { - self.cx.borrowck_context.constraints.liveness_constraints - .add_element(live_region, location); - } if !closure_bounds.is_empty() { let combined_bounds_mapping = closure_bounds @@ -759,13 +741,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { PlaceTy { ty, variant_index: Some(variant_index) } => match ty.kind { ty::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs), ty::Generator(def_id, substs, _) => { - let mut variants = substs.as_generator().state_tys(def_id, tcx); + let mut variants = substs.state_tys(def_id, tcx); let mut variant = match variants.nth(variant_index.into()) { Some(v) => v, None => { bug!("variant_index of generator out of range: {:?}/{:?}", variant_index, - substs.as_generator().state_tys(def_id, tcx).count()) + substs.state_tys(def_id, tcx).count()) } }; return match variant.nth(field.index()) { @@ -781,20 +763,20 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { ty::Adt(adt_def, substs) if !adt_def.is_enum() => (&adt_def.variants[VariantIdx::new(0)], substs), ty::Closure(def_id, substs) => { - return match substs.as_closure().upvar_tys(def_id, tcx).nth(field.index()) { + return match substs.upvar_tys(def_id, tcx).nth(field.index()) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.as_closure().upvar_tys(def_id, tcx).count(), + field_count: substs.upvar_tys(def_id, tcx).count(), }), } } ty::Generator(def_id, substs, _) => { // Only prefix fields (upvars and current state) are // accessible without a variant index. - return match substs.as_generator().prefix_tys(def_id, tcx).nth(field.index()) { + return match substs.prefix_tys(def_id, tcx).nth(field.index()) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.as_generator().prefix_tys(def_id, tcx).count(), + field_count: substs.prefix_tys(def_id, tcx).count(), }), } } @@ -1366,8 +1348,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // they are not caused by the user, but rather artifacts // of lowering. Assignments to other sorts of places *are* interesting // though. - let category = match place.as_local() { - Some(RETURN_PLACE) => if let BorrowCheckContext { + let category = match *place { + Place { + base: PlaceBase::Local(RETURN_PLACE), + projection: box [], + } => if let BorrowCheckContext { universal_regions: UniversalRegions { defining_ty: DefiningTy::Const(def_id, _), @@ -1383,16 +1368,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } else { ConstraintCategory::Return }, - Some(l) if !body.local_decls[l].is_user_variable.is_some() => { + Place { + base: PlaceBase::Local(l), + projection: box [], + } if !body.local_decls[l].is_user_variable.is_some() => { ConstraintCategory::Boring } _ => ConstraintCategory::Assignment, }; let place_ty = place.ty(body, tcx).ty; - let place_ty = self.normalize(place_ty, location); let rv_ty = rv.ty(body, tcx); - let rv_ty = self.normalize(rv_ty, location); if let Err(terr) = self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category) { @@ -1668,9 +1654,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match *destination { Some((ref dest, _target_block)) => { let dest_ty = dest.ty(body, tcx).ty; - let dest_ty = self.normalize(dest_ty, term_location); - let category = match dest.as_local() { - Some(RETURN_PLACE) => { + let category = match *dest { + Place { + base: PlaceBase::Local(RETURN_PLACE), + projection: box [], + } => { if let BorrowCheckContext { universal_regions: UniversalRegions { @@ -1689,7 +1677,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::Return } } - Some(l) if !body.local_decls[l].is_user_variable.is_some() => { + Place { + base: PlaceBase::Local(l), + projection: box [], + } if !body.local_decls[l].is_user_variable.is_some() => { ConstraintCategory::Boring } _ => ConstraintCategory::Assignment, @@ -1735,10 +1726,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { from_hir_call: bool, ) { debug!("check_call_inputs({:?}, {:?})", sig, args); - if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) { + // Do not count the `VaListImpl` argument as a "true" argument to + // a C-variadic function. + let inputs = if sig.c_variadic { + &sig.inputs()[..sig.inputs().len() - 1] + } else { + &sig.inputs()[..] + }; + if args.len() < inputs.len() || (args.len() > inputs.len() && !sig.c_variadic) { span_mirbug!(self, term, "call to {:?} with wrong # of args", sig); } - for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() { + for (n, (fn_arg, op_arg)) in inputs.iter().zip(args).enumerate() { let op_arg_ty = op_arg.ty(body, self.tcx()); let category = if from_hir_call { ConstraintCategory::CallArgument @@ -1943,10 +1941,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } AggregateKind::Closure(def_id, substs) => { - match substs.as_closure().upvar_tys(def_id, tcx).nth(field_index) { + match substs.upvar_tys(def_id, tcx).nth(field_index) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.as_closure().upvar_tys(def_id, tcx).count(), + field_count: substs.upvar_tys(def_id, tcx).count(), }), } } @@ -1954,10 +1952,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // It doesn't make sense to look at a field beyond the prefix; // these require a variant index, and are not initialized in // aggregate rvalues. - match substs.as_generator().prefix_tys(def_id, tcx).nth(field_index) { + match substs.prefix_tys(def_id, tcx).nth(field_index) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.as_generator().prefix_tys(def_id, tcx).count(), + field_count: substs.prefix_tys(def_id, tcx).count(), }), } } @@ -2059,7 +2057,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => { let sig = match op.ty(body, tcx).kind { ty::Closure(def_id, substs) => { - substs.as_closure().sig_ty(def_id, tcx).fn_sig(tcx) + substs.closure_sig_ty(def_id, tcx).fn_sig(tcx) } _ => bug!(), }; @@ -2420,7 +2418,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { location, borrow_region, borrowed_place ); - let mut cursor = borrowed_place.projection.as_ref(); + let mut cursor = &*borrowed_place.projection; while let [proj_base @ .., elem] = cursor { cursor = proj_base; @@ -2531,8 +2529,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // desugaring. A closure gets desugared to a struct, and // these extra requirements are basically like where // clauses on the struct. - AggregateKind::Closure(def_id, substs) - | AggregateKind::Generator(def_id, substs, _) => { + AggregateKind::Closure(def_id, ty::ClosureSubsts { substs }) + | AggregateKind::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { self.prove_closure_bounds(tcx, *def_id, substs, location) } diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs index 80bf0478128c7..2549aa4fbff93 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs @@ -66,9 +66,9 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { self.infcx.create_next_universe() } - fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> { + fn next_existential_region_var(&mut self) -> ty::Region<'tcx> { if let Some(_) = &mut self.borrowck_context { - let origin = NLLRegionVariableOrigin::Existential { from_forall }; + let origin = NLLRegionVariableOrigin::Existential; self.infcx.next_nll_region_var(origin) } else { self.infcx.tcx.lifetimes.re_erased @@ -88,9 +88,7 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { self.infcx - .next_nll_region_var_in_universe(NLLRegionVariableOrigin::Existential { - from_forall: false - }, universe) + .next_nll_region_var_in_universe(NLLRegionVariableOrigin::Existential, universe) } fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) { diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index b876fd83ec983..9f9450188fa94 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -16,12 +16,11 @@ use either::Either; use rustc::hir::def_id::DefId; use rustc::hir::{self, BodyOwnerKind, HirId}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; -use rustc::middle::lang_items; use rustc::ty::fold::TypeFoldable; -use rustc::ty::subst::{InternalSubsts, SubstsRef, Subst}; -use rustc::ty::{self, RegionVid, Ty, TyCtxt}; +use rustc::ty::subst::{InternalSubsts, SubstsRef}; +use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_errors::DiagnosticBuilder; use std::iter; @@ -85,12 +84,12 @@ pub struct UniversalRegions<'tcx> { pub enum DefiningTy<'tcx> { /// The MIR is a closure. The signature is found via /// `ClosureSubsts::closure_sig_ty`. - Closure(DefId, SubstsRef<'tcx>), + Closure(DefId, ty::ClosureSubsts<'tcx>), /// The MIR is a generator. The signature is that generators take /// no parameters and return the result of /// `ClosureSubsts::generator_return_ty`. - Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability), + Generator(DefId, ty::GeneratorSubsts<'tcx>, hir::GeneratorMovability), /// The MIR is a fn item with the given `DefId` and substs. The signature /// of the function can be bound then with the `fn_sig` query. @@ -109,11 +108,9 @@ impl<'tcx> DefiningTy<'tcx> { /// match up with the upvar order in the HIR, typesystem, and MIR. pub fn upvar_tys(self, tcx: TyCtxt<'tcx>) -> impl Iterator> + 'tcx { match self { - DefiningTy::Closure(def_id, substs) => Either::Left( - substs.as_closure().upvar_tys(def_id, tcx) - ), + DefiningTy::Closure(def_id, substs) => Either::Left(substs.upvar_tys(def_id, tcx)), DefiningTy::Generator(def_id, substs, _) => { - Either::Right(Either::Left(substs.as_generator().upvar_tys(def_id, tcx))) + Either::Right(Either::Left(substs.upvar_tys(def_id, tcx))) } DefiningTy::FnDef(..) | DefiningTy::Const(..) => { Either::Right(Either::Right(iter::empty())) @@ -146,7 +143,7 @@ struct UniversalRegionIndices<'tcx> { indices: FxHashMap, RegionVid>, } -#[derive(Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum RegionClassification { /// A **global** region is one that can be named from /// anywhere. There is only one, `'static`. @@ -314,7 +311,7 @@ impl<'tcx> UniversalRegions<'tcx> { err.note(&format!( "defining type: {:?} with closure substs {:#?}", def_id, - &substs[..] + &substs.substs[..] )); // FIXME: It'd be nice to print the late-bound regions @@ -334,7 +331,7 @@ impl<'tcx> UniversalRegions<'tcx> { err.note(&format!( "defining type: {:?} with generator substs {:#?}", def_id, - &substs[..] + &substs.substs[..] )); // FIXME: As above, we'd like to print out the region @@ -428,33 +425,12 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { .replace_late_bound_regions_with_nll_infer_vars(self.mir_def_id, &mut indices); } - let (unnormalized_output_ty, mut unnormalized_input_tys) = - inputs_and_output.split_last().unwrap(); - - // C-variadic fns also have a `VaList` input that's not listed in the signature - // (as it's created inside the body itself, not passed in from outside). - if let DefiningTy::FnDef(def_id, _) = defining_ty { - if self.infcx.tcx.fn_sig(def_id).c_variadic() { - let va_list_did = self.infcx.tcx.require_lang_item( - lang_items::VaListTypeLangItem, - Some(self.infcx.tcx.def_span(self.mir_def_id),), - ); - let region = self.infcx.tcx.mk_region(ty::ReVar( - self.infcx.next_nll_region_var(FR).to_region_vid(), - )); - let va_list_ty = self.infcx.tcx.type_of(va_list_did) - .subst(self.infcx.tcx, &[region.into()]); - - unnormalized_input_tys = self.infcx.tcx.mk_type_list( - unnormalized_input_tys.iter().copied() - .chain(iter::once(va_list_ty)), - ); - } - } - let fr_fn_body = self.infcx.next_nll_region_var(FR).to_region_vid(); let num_universals = self.infcx.num_region_vars(); + let (unnormalized_output_ty, unnormalized_input_tys) = + inputs_and_output.split_last().unwrap(); + debug!( "build: global regions = {}..{}", FIRST_GLOBAL_INDEX, first_extern_index @@ -470,7 +446,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let yield_ty = match defining_ty { DefiningTy::Generator(def_id, substs, _) => { - Some(substs.as_generator().yield_ty(def_id, self.infcx.tcx)) + Some(substs.yield_ty(def_id, self.infcx.tcx)) } _ => None, }; @@ -548,8 +524,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id); let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id); let fr_substs = match defining_ty { - DefiningTy::Closure(_, ref substs) - | DefiningTy::Generator(_, ref substs, _) => { + DefiningTy::Closure(_, ClosureSubsts { ref substs }) + | DefiningTy::Generator(_, GeneratorSubsts { ref substs }, _) => { // In the case of closures, we rely on the fact that // the first N elements in the ClosureSubsts are // inherited from the `closure_base_def_id`. @@ -584,7 +560,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { match defining_ty { DefiningTy::Closure(def_id, substs) => { assert_eq!(self.mir_def_id, def_id); - let closure_sig = substs.as_closure().sig_ty(def_id, tcx).fn_sig(tcx); + let closure_sig = substs.closure_sig_ty(def_id, tcx).fn_sig(tcx); let inputs_and_output = closure_sig.inputs_and_output(); let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap(); ty::Binder::fuse( @@ -612,7 +588,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { DefiningTy::Generator(def_id, substs, movability) => { assert_eq!(self.mir_def_id, def_id); - let output = substs.as_generator().return_ty(def_id, tcx); + let output = substs.return_ty(def_id, tcx); let generator_ty = tcx.mk_generator(def_id, substs, movability); let inputs_and_output = self.infcx.tcx.intern_type_list(&[generator_ty, output]); ty::Binder::dummy(inputs_and_output) @@ -790,7 +766,7 @@ fn for_each_late_bound_region_defined_on<'tcx>( owner: fn_def_id.index, local_id: *late_bound, }; - let name = tcx.hir().name(hir_id); + let name = tcx.hir().name(hir_id).as_interned_str(); let region_def_id = tcx.hir().local_def_id(hir_id); let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion { scope: fn_def_id, diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 264e4807af07e..9dd3e119c217a 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -64,8 +64,14 @@ pub(super) fn borrow_conflicts_with_place<'tcx>( // This Local/Local case is handled by the more general code below, but // it's so common that it's a speed win to check for it first. - if let Some(l1) = borrow_place.as_local() { - if let Some(l2) = access_place.as_local() { + if let Place { + base: PlaceBase::Local(l1), + projection: box [], + } = borrow_place { + if let PlaceRef { + base: PlaceBase::Local(l2), + projection: [], + } = access_place { return l1 == l2; } } diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index 95471afb7884f..695080dfe23d9 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -1,5 +1,7 @@ use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::mir::{Local, Location, Place, PlaceBase, Statement, StatementKind, TerminatorKind}; +use rustc::mir::{ + Local, Location, Place, PlaceBase, Statement, StatementKind, TerminatorKind +}; use rustc_data_structures::fx::FxHashSet; @@ -116,7 +118,10 @@ impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tc "assignment of {:?} to {:?}, adding {:?} to used mutable set", path.place, local, path.place ); - if let Some(user_local) = path.place.as_local() { + if let Place { + base: PlaceBase::Local(user_local), + projection: box [], + } = path.place { self.mbcx.used_mut.insert(user_local); } } diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 8d2bef39bed42..09b33c6654a9d 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -6,79 +6,13 @@ use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::hair::*; use rustc::mir::interpret::{PanicInfo::BoundsCheck}; use rustc::mir::*; -use rustc::ty::{CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance}; +use rustc::ty::{CanonicalUserTypeAnnotation, Variance}; -use rustc_index::vec::Idx; - -/// `PlaceBuilder` is used to create places during MIR construction. It allows you to "build up" a -/// place by pushing more and more projections onto the end, and then convert the final set into a -/// place using the `into_place` method. -/// -/// This is used internally when building a place for an expression like `a.b.c`. The fields `b` -/// and `c` can be progressively pushed onto the place builder that is created when converting `a`. -#[derive(Clone)] -struct PlaceBuilder<'tcx> { - base: PlaceBase<'tcx>, - projection: Vec>, -} - -impl PlaceBuilder<'tcx> { - fn into_place(self, tcx: TyCtxt<'tcx>) -> Place<'tcx> { - Place { - base: self.base, - projection: tcx.intern_place_elems(&self.projection), - } - } - - fn field(self, f: Field, ty: Ty<'tcx>) -> Self { - self.project(PlaceElem::Field(f, ty)) - } - - fn deref(self) -> Self { - self.project(PlaceElem::Deref) - } - - fn index(self, index: Local) -> Self { - self.project(PlaceElem::Index(index)) - } - - fn project(mut self, elem: PlaceElem<'tcx>) -> Self { - self.projection.push(elem); - self - } -} - -impl From for PlaceBuilder<'tcx> { - fn from(local: Local) -> Self { - Self { - base: local.into(), - projection: Vec::new(), - } - } -} - -impl From> for PlaceBuilder<'tcx> { - fn from(base: PlaceBase<'tcx>) -> Self { - Self { - base, - projection: Vec::new(), - } - } -} +use rustc_data_structures::indexed_vec::Idx; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, yielding a place that we can move from etc. - pub fn as_place(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { - let place_builder = unpack!(block = self.as_place_builder(block, expr)); - block.and(place_builder.into_place(self.hir.tcx())) - } - - /// This is used when constructing a compound `Place`, so that we can avoid creating - /// intermediate `Place` values until we know the full set of projections. - fn as_place_builder(&mut self, block: BasicBlock, expr: M) -> BlockAnd> + pub fn as_place(&mut self, block: BasicBlock, expr: M) -> BlockAnd> where M: Mirror<'tcx, Output = Expr<'tcx>>, { @@ -91,25 +25,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// place. The place itself may or may not be mutable: /// * If this expr is a place expr like a.b, then we will return that place. /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary. - pub fn as_read_only_place(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { - let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr)); - block.and(place_builder.into_place(self.hir.tcx())) - } - - /// This is used when constructing a compound `Place`, so that we can avoid creating - /// intermediate `Place` values until we know the full set of projections. - /// Mutability note: The caller of this method promises only to read from the resulting - /// place. The place itself may or may not be mutable: - /// * If this expr is a place expr like a.b, then we will return that place. - /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary. - fn as_read_only_place_builder( - &mut self, - block: BasicBlock, - expr: M, - ) -> BlockAnd> + pub fn as_read_only_place(&mut self, block: BasicBlock, expr: M) -> BlockAnd> where M: Mirror<'tcx, Output = Expr<'tcx>>, { @@ -122,7 +38,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mut block: BasicBlock, expr: Expr<'tcx>, mutability: Mutability, - ) -> BlockAnd> { + ) -> BlockAnd> { debug!( "expr_as_place(block={:?}, expr={:?}, mutability={:?})", block, expr, mutability @@ -138,23 +54,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { value, } => this.in_scope((region_scope, source_info), lint_level, |this| { if mutability == Mutability::Not { - this.as_read_only_place_builder(block, value) + this.as_read_only_place(block, value) } else { - this.as_place_builder(block, value) + this.as_place(block, value) } }), ExprKind::Field { lhs, name } => { - let place_builder = unpack!(block = this.as_place_builder(block, lhs)); - block.and(place_builder.field(name, expr.ty)) + let place = unpack!(block = this.as_place(block, lhs)); + let place = place.field(name, expr.ty); + block.and(place) } ExprKind::Deref { arg } => { - let place_builder = unpack!(block = this.as_place_builder(block, arg)); - block.and(place_builder.deref()) + let place = unpack!(block = this.as_place(block, arg)); + let place = place.deref(); + block.and(place) } ExprKind::Index { lhs, index } => { let (usize_ty, bool_ty) = (this.hir.usize_ty(), this.hir.bool_ty()); - let place_builder = unpack!(block = this.as_place_builder(block, lhs)); + let slice = unpack!(block = this.as_place(block, lhs)); // Making this a *fresh* temporary also means we do not have to worry about // the index changing later: Nothing will ever change this temporary. // The "retagging" transformation (for Stacked Borrows) relies on this. @@ -165,7 +83,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Mutability::Not, )); - let slice = place_builder.clone().into_place(this.hir.tcx()); // bounds check: let (len, lt) = ( this.temp(usize_ty.clone(), expr_span), @@ -175,7 +92,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, source_info, // len = len(slice) &len, - Rvalue::Len(slice), + Rvalue::Len(slice.clone()), ); this.cfg.push_assign( block, @@ -193,29 +110,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { index: Operand::Copy(Place::from(idx)), }; let success = this.assert(block, Operand::Move(lt), true, msg, expr_span); - success.and(place_builder.index(idx)) + success.and(slice.index(idx)) } - ExprKind::SelfRef => block.and(PlaceBuilder::from(Local::new(1))), + ExprKind::SelfRef => block.and(Place::from(Local::new(1))), ExprKind::VarRef { id } => { - let place_builder = if this.is_bound_var_in_guard(id) { + let place = if this.is_bound_var_in_guard(id) { let index = this.var_local_id(id, RefWithinGuard); - PlaceBuilder::from(index).deref() + Place::from(index).deref() } else { let index = this.var_local_id(id, OutsideGuard); - PlaceBuilder::from(index) + Place::from(index) }; - block.and(place_builder) + block.and(place) } - ExprKind::StaticRef { id } => block.and(PlaceBuilder::from( - PlaceBase::Static(Box::new(Static { + ExprKind::StaticRef { id } => block.and(Place { + base: PlaceBase::Static(Box::new(Static { ty: expr.ty, kind: StaticKind::Static, def_id: id, - })) - )), + })), + projection: box [], + }), ExprKind::PlaceTypeAscription { source, user_ty } => { - let place_builder = unpack!(block = this.as_place_builder(block, source)); + let place = unpack!(block = this.as_place(block, source)); if let Some(user_ty) = user_ty { let annotation_index = this.canonical_user_type_annotations.push( CanonicalUserTypeAnnotation { @@ -224,15 +142,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { inferred_ty: expr.ty, } ); - - let place = place_builder.clone().into_place(this.hir.tcx()); this.cfg.push( block, Statement { source_info, kind: StatementKind::AscribeUserType( box( - place, + place.clone(), UserTypeProjection { base: annotation_index, projs: vec![], } ), Variance::Invariant, @@ -240,7 +156,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, ); } - block.and(place_builder) + block.and(place) } ExprKind::ValueTypeAscription { source, user_ty } => { let source = this.hir.mirror(source); @@ -269,7 +185,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, ); } - block.and(PlaceBuilder::from(temp)) + block.and(Place::from(temp)) } ExprKind::Array { .. } @@ -305,7 +221,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }); let temp = unpack!(block = this.as_temp(block, expr.temp_lifetime, expr, mutability)); - block.and(PlaceBuilder::from(temp)) + block.and(Place::from(temp)) } } } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 4f1ac8e51dc20..7dfe98cbebfc2 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -1,7 +1,7 @@ //! See docs in `build/expr/mod.rs`. use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; @@ -128,6 +128,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_span, scope, result, + expr.ty, ); } @@ -139,7 +140,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // initialize the box contents: unpack!( block = this.into( - &this.hir.tcx().mk_place_deref(Place::from(result)), + &Place::from(result).deref(), block, value ) ); @@ -296,13 +297,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .zip(field_types.into_iter()) .map(|(n, ty)| match fields_map.get(&n) { Some(v) => v.clone(), - None => this.consume_by_copy_or_move(this.hir.tcx().mk_place_field( - base.clone(), - n, - ty, - )), - }) - .collect() + None => this.consume_by_copy_or_move(base.clone().field(n, ty)), + }).collect() } else { field_names .iter() @@ -402,9 +398,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let val_fld = Field::new(0); let of_fld = Field::new(1); - let tcx = self.hir.tcx(); - let val = tcx.mk_place_field(result_value.clone(), val_fld, ty); - let of = tcx.mk_place_field(result_value, of_fld, bool_ty); + let val = result_value.clone().field(val_fld, ty); + let of = result_value.field(of_fld, bool_ty); let err = PanicInfo::Overflow(op); @@ -502,14 +497,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let arg_place = unpack!(block = this.as_place(block, arg)); - let mutability = match arg_place.as_ref() { - PlaceRef { - base: &PlaceBase::Local(local), - projection: &[], + let mutability = match arg_place { + Place { + base: PlaceBase::Local(local), + projection: box [], } => this.local_decls[local].mutability, - PlaceRef { - base: &PlaceBase::Local(local), - projection: &[ProjectionElem::Deref], + Place { + base: PlaceBase::Local(local), + projection: box [ProjectionElem::Deref], } => { debug_assert!( this.local_decls[local].is_ref_for_guard(), @@ -517,13 +512,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); this.local_decls[local].mutability } - PlaceRef { + Place { ref base, - projection: &[ref proj_base @ .., ProjectionElem::Field(upvar_index, _)], + projection: box [ref proj_base @ .., ProjectionElem::Field(upvar_index, _)], } - | PlaceRef { + | Place { ref base, - projection: &[ + projection: box [ ref proj_base @ .., ProjectionElem::Field(upvar_index, _), ProjectionElem::Deref @@ -574,6 +569,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { upvar_span, temp_lifetime, temp, + upvar_ty, ); } diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 18332ed68f8bd..dbcc330eca382 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -103,6 +103,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_span, temp_lifetime, temp, + expr_ty, DropKind::Storage, ); } @@ -116,6 +117,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_span, temp_lifetime, temp, + expr_ty, DropKind::Value, ); } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index e7388b920548b..8a6bc5a2a764e 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -235,7 +235,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }); let ptr_temp = Place::from(ptr_temp); let block = unpack!(this.into(&ptr_temp, block, ptr)); - this.into(&this.hir.tcx().mk_place_deref(ptr_temp), block, val) + this.into(&ptr_temp.deref(), block, val) } else { let args: Vec<_> = args .into_iter() diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 667b37bbd80c8..8db06aa375e23 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -15,7 +15,7 @@ use rustc::mir::*; use rustc::middle::region; use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty}; use rustc::ty::layout::VariantIdx; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use syntax::ast::Name; use syntax_pos::Span; @@ -535,18 +535,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { kind: StatementKind::StorageLive(local_id), }, ); + let var_ty = self.local_decls[local_id].ty; let region_scope = self.hir.region_scope_tree.var_scope(var.local_id); - self.schedule_drop(span, region_scope, local_id, DropKind::Storage); + self.schedule_drop(span, region_scope, local_id, var_ty, DropKind::Storage); Place::from(local_id) } pub fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) { let local_id = self.var_local_id(var, for_guard); + let var_ty = self.local_decls[local_id].ty; let region_scope = self.hir.region_scope_tree.var_scope(var.local_id); self.schedule_drop( span, region_scope, local_id, + var_ty, DropKind::Value, ); } @@ -948,7 +951,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fake_borrows.insert(Place { base: source.base.clone(), - projection: self.hir.tcx().intern_place_elems(proj_base), + projection: proj_base.to_vec().into_boxed_slice(), }); } } @@ -1293,7 +1296,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Insert a Shallow borrow of the prefixes of any fake borrows. for place in fake_borrows { - let mut cursor = place.projection.as_ref(); + let mut cursor = &*place.projection; while let [proj_base @ .., elem] = cursor { cursor = proj_base; @@ -1488,7 +1491,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { BorrowKind::Shallow, Place { base: place.base.clone(), - projection: tcx.intern_place_elems(place.projection), + projection: place.projection.to_vec().into_boxed_slice(), }, ); self.cfg.push_assign( diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 9b7bccca2ddf3..3826e5e3ba5e6 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -166,7 +166,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } }); if irrefutable { - let place = tcx.mk_place_downcast(match_pair.place, adt_def, variant_index); + let place = match_pair.place.downcast(adt_def, variant_index); candidate.match_pairs.extend(self.field_match_pairs(place, subpatterns)); Ok(()) } else { @@ -191,7 +191,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } PatKind::Deref { ref subpattern } => { - let place = tcx.mk_place_deref(match_pair.place); + let place = match_pair.place.deref(); candidate.match_pairs.push(MatchPair::new(place, subpattern)); Ok(()) } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 5c2f72c0a061f..d8bb0b4f6cc57 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -9,9 +9,9 @@ use crate::build::Builder; use crate::build::matches::{Candidate, MatchPair, Test, TestKind}; use crate::hair::*; use crate::hair::pattern::compare_const_vals; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::FxHashMap; -use rustc::ty::{self, Ty, adjustment::PointerCast}; +use rustc::ty::{self, Ty, adjustment::{PointerCast}}; use rustc::ty::util::IntTypeExt; use rustc::ty::layout::VariantIdx; use rustc::mir::*; @@ -743,21 +743,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate: &mut Candidate<'pat, 'tcx>, ) { let match_pair = candidate.match_pairs.remove(match_pair_index); - let tcx = self.hir.tcx(); // So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`, // we want to create a set of derived match-patterns like // `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`. let elem = ProjectionElem::Downcast( Some(adt_def.variants[variant_index].ident.name), variant_index); - let downcast_place = tcx.mk_place_elem(match_pair.place, elem); // `(x as Variant)` - let consequent_match_pairs = subpatterns.iter().map(|subpattern| { - // e.g., `(x as Variant).0` - let place = - tcx.mk_place_field(downcast_place.clone(), subpattern.field, subpattern.pattern.ty); - // e.g., `(x as Variant).0 @ P1` - MatchPair::new(place, &subpattern.pattern) - }); + let downcast_place = match_pair.place.elem(elem); // `(x as Variant)` + let consequent_match_pairs = + subpatterns.iter() + .map(|subpattern| { + // e.g., `(x as Variant).0` + let place = downcast_place.clone().field(subpattern.field, + subpattern.pattern.ty); + // e.g., `(x as Variant).0 @ P1` + MatchPair::new(place, &subpattern.pattern) + }); candidate.match_pairs.extend(consequent_match_pairs); } diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir/build/matches/util.rs index 917535f31dc4b..83fb924af6381 100644 --- a/src/librustc_mir/build/matches/util.rs +++ b/src/librustc_mir/build/matches/util.rs @@ -6,22 +6,17 @@ use std::u32; use std::convert::TryInto; impl<'a, 'tcx> Builder<'a, 'tcx> { - pub fn field_match_pairs<'pat>( - &mut self, - place: Place<'tcx>, - subpatterns: &'pat [FieldPat<'tcx>], - ) -> Vec> { - subpatterns - .iter() - .map(|fieldpat| { - let place = self.hir.tcx().mk_place_field( - place.clone(), - fieldpat.field, - fieldpat.pattern.ty, - ); - MatchPair::new(place, &fieldpat.pattern) - }) - .collect() + pub fn field_match_pairs<'pat>(&mut self, + place: Place<'tcx>, + subpatterns: &'pat [FieldPat<'tcx>]) + -> Vec> { + subpatterns.iter() + .map(|fieldpat| { + let place = place.clone().field(fieldpat.field, + fieldpat.pattern.ty); + MatchPair::new(place, &fieldpat.pattern) + }) + .collect() } pub fn prefix_slice_suffix<'pat>(&mut self, @@ -32,7 +27,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { suffix: &'pat [Pat<'tcx>]) { let min_length = prefix.len() + suffix.len(); let min_length = min_length.try_into().unwrap(); - let tcx = self.hir.tcx(); match_pairs.extend( prefix.iter() @@ -43,13 +37,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { min_length, from_end: false, }; - let place = tcx.mk_place_elem(place.clone(), elem); + let place = place.clone().elem(elem); MatchPair::new(place, subpattern) }) ); if let Some(subslice_pat) = opt_slice { - let subslice = tcx.mk_place_elem(place.clone(),ProjectionElem::Subslice { + let subslice = place.clone().elem(ProjectionElem::Subslice { from: prefix.len() as u32, to: suffix.len() as u32 }); @@ -66,7 +60,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { min_length, from_end: true, }; - let place = tcx.mk_place_elem(place.clone(), elem); + let place = place.clone().elem(elem); MatchPair::new(place, subpattern) }) ); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index ffb70180bbb4b..f1e045302eced 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -7,14 +7,12 @@ use crate::util as mir_util; use rustc::hir; use rustc::hir::Node; use rustc::hir::def_id::DefId; -use rustc::middle::lang_items; use rustc::middle::region; use rustc::mir::*; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::subst::Subst; use rustc::util::nodemap::HirIdMap; use rustc_target::spec::PanicStrategy; -use rustc_index::vec::{IndexVec, Idx}; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use std::u32; use rustc_target::spec::abi::Abi; use syntax::attr::{self, UnwindAttr}; @@ -104,7 +102,9 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { let opt_ty_info; let self_arg; if let Some(ref fn_decl) = tcx.hir().fn_decl_by_hir_id(owner_id) { - opt_ty_info = fn_decl.inputs.get(index).map(|ty| ty.span); + let ty_hir_id = fn_decl.inputs[index].hir_id; + let ty_span = tcx.hir().span(ty_hir_id); + opt_ty_info = Some(ty_span); self_arg = if index == 0 && fn_decl.implicit_self.has_implicit_self() { match fn_decl.implicit_self { hir::ImplicitSelfKind::Imm => Some(ImplicitSelfKind::Imm), @@ -121,24 +121,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { self_arg = None; } - // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` - // (as it's created inside the body itself, not passed in from outside). - let ty = if fn_sig.c_variadic && index == fn_sig.inputs().len() { - let va_list_did = tcx.require_lang_item( - lang_items::VaListTypeLangItem, - Some(arg.span), - ); - let region = tcx.mk_region(ty::ReScope(region::Scope { - id: body.value.hir_id.local_id, - data: region::ScopeData::CallSite - })); - - tcx.type_of(va_list_did).subst(tcx, &[region.into()]) - } else { - fn_sig.inputs()[index] - }; - - ArgInfo(ty, opt_ty_info, Some(&arg), self_arg) + ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&arg), self_arg) }); let arguments = implicit_argument.into_iter().chain(explicit_arguments); @@ -146,7 +129,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { let (yield_ty, return_ty) = if body.generator_kind.is_some() { let gen_sig = match ty.kind { ty::Generator(gen_def_id, gen_substs, ..) => - gen_substs.as_generator().sig(gen_def_id, tcx), + gen_substs.sig(gen_def_id, tcx), _ => span_bug!(tcx.hir().span(id), "generator w/o generator type: {:?}", ty), @@ -455,7 +438,7 @@ struct CFG<'tcx> { basic_blocks: IndexVec>, } -rustc_index::newtype_index! { +newtype_index! { pub struct ScopeId { .. } } @@ -502,21 +485,24 @@ macro_rules! unpack { }; } -fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, _abi: Abi) -> bool { - // Validate `#[unwind]` syntax regardless of platform-specific panic strategy. +fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, abi: Abi) -> bool { + // Not callable from C, so we can safely unwind through these + if abi == Abi::Rust || abi == Abi::RustCall { return false; } + + // Validate `#[unwind]` syntax regardless of platform-specific panic strategy let attrs = &tcx.get_attrs(fn_def_id); let unwind_attr = attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs); - // We never unwind, so it's not relevant to stop an unwind. + // We never unwind, so it's not relevant to stop an unwind if tcx.sess.panic_strategy() != PanicStrategy::Unwind { return false; } - // We cannot add landing pads, so don't add one. + // We cannot add landing pads, so don't add one if tcx.sess.no_landing_pads() { return false; } // This is a special case: some functions have a C abi but are meant to // unwind anyway. Don't stop them. match unwind_attr { - None => false, // FIXME(#58794); should be `!(abi == Abi::Rust || abi == Abi::RustCall)` + None => false, // FIXME(#58794) Some(UnwindAttr::Allowed) => false, Some(UnwindAttr::Aborts) => true, } @@ -826,12 +812,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Function arguments always get the first Local indices after the return place let local = Local::new(index + 1); let place = Place::from(local); - let &ArgInfo(_, opt_ty_info, arg_opt, ref self_binding) = arg_info; + let &ArgInfo(ty, opt_ty_info, arg_opt, ref self_binding) = arg_info; // Make sure we drop (parts of) the argument even when not matched on. self.schedule_drop( arg_opt.as_ref().map_or(ast_body.span, |arg| arg.pat.span), - argument_scope, local, DropKind::Value, + argument_scope, local, ty, DropKind::Value, ); if let Some(arg) = arg_opt { diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 1b3d8641f204e..a26ec72584bda 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -85,6 +85,7 @@ should go to. use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG}; use crate::hair::{Expr, ExprRef, LintLevel}; use rustc::middle::region; +use rustc::ty::Ty; use rustc::hir; use rustc::mir::*; use syntax_pos::{DUMMY_SP, Span}; @@ -172,11 +173,11 @@ struct BreakableScope<'tcx> { region_scope: region::Scope, /// Where the body of the loop begins. `None` if block continue_block: Option, - /// Block to branch into when the loop or block terminates (either by being - /// `break`-en out from, or by having its condition to become false) + /// Block to branch into when the loop or block terminates (either by being `break`-en out + /// from, or by having its condition to become false) break_block: BasicBlock, - /// The destination of the loop/block expression itself (i.e., where to put - /// the result of a `break` expression) + /// The destination of the loop/block expression itself (i.e., where to put the result of a + /// `break` expression) break_destination: Place<'tcx>, } @@ -727,9 +728,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: Span, region_scope: region::Scope, local: Local, + place_ty: Ty<'tcx>, ) { - self.schedule_drop(span, region_scope, local, DropKind::Storage); - self.schedule_drop(span, region_scope, local, DropKind::Value); + self.schedule_drop(span, region_scope, local, place_ty, DropKind::Storage); + self.schedule_drop(span, region_scope, local, place_ty, DropKind::Value); } /// Indicates that `place` should be dropped on exit from @@ -742,13 +744,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: Span, region_scope: region::Scope, local: Local, + place_ty: Ty<'tcx>, drop_kind: DropKind, ) { - let needs_drop = match drop_kind { - DropKind::Value => { - if !self.hir.needs_drop(self.local_decls[local].ty) { return } - true - }, + let needs_drop = self.hir.needs_drop(place_ty); + match drop_kind { + DropKind::Value => if !needs_drop { return }, DropKind::Storage => { if local.index() <= self.arg_count { span_bug!( @@ -757,9 +758,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.arg_count, ) } - false } - }; + } for scope in self.scopes.iter_mut() { let this_scope = scope.region_scope == region_scope; @@ -926,43 +926,46 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // If constants and statics, we don't generate StorageLive for this // temporary, so don't try to generate StorageDead for it either. _ if self.local_scope().is_none() => (), - Operand::Copy(place) - | Operand::Move(place) => { - if let Some(cond_temp) = place.as_local() { - // Manually drop the condition on both branches. - let top_scope = self.scopes.scopes.last_mut().unwrap(); - let top_drop_data = top_scope.drops.pop().unwrap(); - - match top_drop_data.kind { - DropKind::Value { .. } => { - bug!("Drop scheduled on top of condition variable") - } - DropKind::Storage => { - let source_info = top_scope.source_info(top_drop_data.span); - let local = top_drop_data.local; - assert_eq!(local, cond_temp, "Drop scheduled on top of condition"); - self.cfg.push( - true_block, - Statement { - source_info, - kind: StatementKind::StorageDead(local) - }, - ); - self.cfg.push( - false_block, - Statement { - source_info, - kind: StatementKind::StorageDead(local) - }, - ); - } + Operand::Copy(Place { + base: PlaceBase::Local(cond_temp), + projection: box [], + }) + | Operand::Move(Place { + base: PlaceBase::Local(cond_temp), + projection: box [], + }) => { + // Manually drop the condition on both branches. + let top_scope = self.scopes.scopes.last_mut().unwrap(); + let top_drop_data = top_scope.drops.pop().unwrap(); + + match top_drop_data.kind { + DropKind::Value { .. } => { + bug!("Drop scheduled on top of condition variable") + } + DropKind::Storage => { + let source_info = top_scope.source_info(top_drop_data.span); + let local = top_drop_data.local; + assert_eq!(local, cond_temp, "Drop scheduled on top of condition"); + self.cfg.push( + true_block, + Statement { + source_info, + kind: StatementKind::StorageDead(local) + }, + ); + self.cfg.push( + false_block, + Statement { + source_info, + kind: StatementKind::StorageDead(local) + }, + ); } - - top_scope.invalidate_cache(true, self.is_generator, true); - } else { - bug!("Expected as_local_operand to produce a temporary"); } + + top_scope.invalidate_cache(true, self.is_generator, true); } + _ => bug!("Expected as_local_operand to produce a temporary"), } (true_block, false_block) diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs index e0ca10535237b..f0014602e2d6b 100644 --- a/src/librustc_mir/dataflow/at_location.rs +++ b/src/librustc_mir/dataflow/at_location.rs @@ -2,7 +2,7 @@ //! locations. use rustc::mir::{BasicBlock, Location}; -use rustc_index::bit_set::{BitIter, BitSet, HybridBitSet}; +use rustc_data_structures::bit_set::{BitIter, BitSet, HybridBitSet}; use crate::dataflow::{BitDenotation, DataflowResults, GenKillSet}; use crate::dataflow::move_paths::{HasMoveData, MovePathIndex}; diff --git a/src/librustc_mir/dataflow/generic.rs b/src/librustc_mir/dataflow/generic.rs index dd6238b80d174..886044c069282 100644 --- a/src/librustc_mir/dataflow/generic.rs +++ b/src/librustc_mir/dataflow/generic.rs @@ -16,24 +16,16 @@ //! [gk]: https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems //! [#64566]: https://github.com/rust-lang/rust/pull/64566 -use std::borrow::Borrow; use std::cmp::Ordering; -use std::ffi::OsString; -use std::path::{Path, PathBuf}; -use std::{fs, io, ops}; +use std::ops; -use rustc::hir::def_id::DefId; use rustc::mir::{self, traversal, BasicBlock, Location}; -use rustc::ty::{self, TyCtxt}; +use rustc_data_structures::bit_set::BitSet; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::work_queue::WorkQueue; -use rustc_index::bit_set::BitSet; -use rustc_index::vec::{Idx, IndexVec}; -use syntax::symbol::sym; use crate::dataflow::BottomValue; -mod graphviz; - /// A specific kind of dataflow analysis. /// /// To run a dataflow analysis, one must set the initial state of the `START_BLOCK` via @@ -70,13 +62,6 @@ pub trait Analysis<'tcx>: BottomValue { /// and try to keep it short. const NAME: &'static str; - /// How each element of your dataflow state will be displayed during debugging. - /// - /// By default, this is the `fmt::Debug` representation of `Self::Idx`. - fn pretty_print_idx(&self, w: &mut impl io::Write, idx: Self::Idx) -> io::Result<()> { - write!(w, "{:?}", idx) - } - /// The size of each bitvector allocated for each block. fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize; @@ -92,7 +77,7 @@ pub trait Analysis<'tcx>: BottomValue { location: Location, ); - /// Updates the current dataflow state with the effect of evaluating a terminator. + /// 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, @@ -195,20 +180,17 @@ impl CursorPosition { } } -type ResultsRefCursor<'a, 'mir, 'tcx, A> = - ResultsCursor<'mir, 'tcx, A, &'a Results<'tcx, A>>; - /// 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, R = Results<'tcx, A>> +pub struct ResultsCursor<'mir, 'tcx, A> where A: Analysis<'tcx>, { body: &'mir mir::Body<'tcx>, - results: R, + results: Results<'tcx, A>, state: BitSet, pos: CursorPosition, @@ -220,29 +202,24 @@ where is_call_return_effect_applied: bool, } -impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R> +impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A> where A: Analysis<'tcx>, - R: Borrow>, { /// Returns a new cursor for `results` that points to the start of the `START_BLOCK`. - pub fn new(body: &'mir mir::Body<'tcx>, results: R) -> Self { + 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.borrow().entry_sets[mir::START_BLOCK].clone(), + state: results.entry_sets[mir::START_BLOCK].clone(), results, } } - pub fn analysis(&self) -> &A { - &self.results.borrow().analysis - } - /// 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.borrow().entry_sets[block]); + self.state.overwrite(&self.results.entry_sets[block]); self.pos = CursorPosition::AtBlockStart(block); self.is_call_return_effect_applied = false; } @@ -298,7 +275,7 @@ where } = &term.kind { if !self.is_call_return_effect_applied { self.is_call_return_effect_applied = true; - self.results.borrow().analysis.apply_call_return_effect( + self.results.analysis.apply_call_return_effect( &mut self.state, target.block, func, @@ -339,7 +316,7 @@ where }; let block_data = &self.body.basic_blocks()[target_block]; - self.results.borrow().analysis.apply_partial_block_effect( + self.results.analysis.apply_partial_block_effect( &mut self.state, target_block, block_data, @@ -372,9 +349,7 @@ where { analysis: A, bits_per_block: usize, - tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, - def_id: DefId, dead_unwinds: &'a BitSet, entry_sets: IndexVec>, } @@ -384,9 +359,7 @@ where A: Analysis<'tcx>, { pub fn new( - tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, - def_id: DefId, dead_unwinds: &'a BitSet, analysis: A, ) -> Self { @@ -404,9 +377,7 @@ where Engine { analysis, bits_per_block, - tcx, body, - def_id, dead_unwinds, entry_sets, } @@ -442,26 +413,10 @@ where ); } - let Engine { - tcx, - body, - def_id, - analysis, - entry_sets, - .. - } = self; - - let results = Results { analysis, entry_sets }; - - let attrs = tcx.get_attrs(def_id); - if let Some(path) = get_dataflow_graphviz_output_path(tcx, attrs, A::NAME) { - let result = write_dataflow_graphviz_results(body, def_id, &path, &results); - if let Err(e) = result { - warn!("Failed to write dataflow results to {}: {}", path.display(), e); - } + Results { + analysis: self.analysis, + entry_sets: self.entry_sets, } - - results } fn propagate_bits_into_graph_successors_of( @@ -555,59 +510,3 @@ where } } } - -/// Looks for attributes like `#[rustc_mir(borrowck_graphviz_postflow="./path/to/suffix.dot")]` and -/// extracts the path with the given analysis name prepended to the suffix. -/// -/// Returns `None` if no such attribute exists. -fn get_dataflow_graphviz_output_path( - tcx: TyCtxt<'tcx>, - attrs: ty::Attributes<'tcx>, - analysis: &str, -) -> Option { - let mut rustc_mir_attrs = attrs - .into_iter() - .filter(|attr| attr.check_name(sym::rustc_mir)) - .flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter())); - - let borrowck_graphviz_postflow = rustc_mir_attrs - .find(|attr| attr.check_name(sym::borrowck_graphviz_postflow))?; - - let path_and_suffix = match borrowck_graphviz_postflow.value_str() { - Some(p) => p, - None => { - tcx.sess.span_err( - borrowck_graphviz_postflow.span(), - "borrowck_graphviz_postflow requires a path", - ); - - return None; - } - }; - - // Change "path/suffix.dot" to "path/analysis_name_suffix.dot" - let mut ret = PathBuf::from(path_and_suffix.to_string()); - let suffix = ret.file_name().unwrap(); - - let mut file_name: OsString = analysis.into(); - file_name.push("_"); - file_name.push(suffix); - ret.set_file_name(file_name); - - Some(ret) -} - -fn write_dataflow_graphviz_results>( - body: &mir::Body<'tcx>, - def_id: DefId, - path: &Path, - results: &Results<'tcx, A> -) -> io::Result<()> { - debug!("printing dataflow results for {:?} to {}", def_id, path.display()); - - let mut buf = Vec::new(); - let graphviz = graphviz::Formatter::new(body, def_id, results); - - dot::render(&graphviz, &mut buf)?; - fs::write(path, buf) -} diff --git a/src/librustc_mir/dataflow/generic/graphviz.rs b/src/librustc_mir/dataflow/generic/graphviz.rs deleted file mode 100644 index 47ace8f33ecac..0000000000000 --- a/src/librustc_mir/dataflow/generic/graphviz.rs +++ /dev/null @@ -1,413 +0,0 @@ -use std::cell::RefCell; -use std::io::{self, Write}; -use std::{ops, str}; - -use rustc::hir::def_id::DefId; -use rustc::mir::{self, BasicBlock, Body, Location}; -use rustc_index::bit_set::{BitSet, HybridBitSet}; -use rustc_index::vec::Idx; - -use crate::util::graphviz_safe_def_name; -use super::{Analysis, Results, ResultsRefCursor}; - -pub struct Formatter<'a, 'tcx, A> -where - A: Analysis<'tcx>, -{ - body: &'a Body<'tcx>, - def_id: DefId, - - // This must be behind a `RefCell` because `dot::Labeller` takes `&self`. - block_formatter: RefCell>, -} - -impl Formatter<'a, 'tcx, A> -where - A: Analysis<'tcx>, -{ - pub fn new( - body: &'a Body<'tcx>, - def_id: DefId, - results: &'a Results<'tcx, A>, - ) -> Self { - let block_formatter = BlockFormatter { - bg: Background::Light, - prev_state: BitSet::new_empty(results.analysis.bits_per_block(body)), - results: ResultsRefCursor::new(body, results), - }; - - Formatter { - body, - def_id, - block_formatter: RefCell::new(block_formatter), - } - } -} - -/// A pair of a basic block and an index into that basic blocks `successors`. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct CfgEdge { - source: BasicBlock, - index: usize, -} - -fn outgoing_edges(body: &Body<'_>, bb: BasicBlock) -> Vec { - body[bb] - .terminator() - .successors() - .enumerate() - .map(|(index, _)| CfgEdge { source: bb, index }) - .collect() -} - -impl dot::Labeller<'_> for Formatter<'a, 'tcx, A> -where - A: Analysis<'tcx>, -{ - type Node = BasicBlock; - type Edge = CfgEdge; - - fn graph_id(&self) -> dot::Id<'_> { - let name = graphviz_safe_def_name(self.def_id); - dot::Id::new(format!("graph_for_def_id_{}", name)).unwrap() - } - - fn node_id(&self, n: &Self::Node) -> dot::Id<'_> { - dot::Id::new(format!("bb_{}", n.index())).unwrap() - } - - fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> { - let mut label = Vec::new(); - self.block_formatter - .borrow_mut() - .write_node_label(&mut label, self.body, *block) - .unwrap(); - dot::LabelText::html(String::from_utf8(label).unwrap()) - } - - fn node_shape(&self, _n: &Self::Node) -> Option> { - Some(dot::LabelText::label("none")) - } - - fn edge_label(&self, e: &Self::Edge) -> dot::LabelText<'_> { - let label = &self.body - [e.source] - .terminator() - .kind - .fmt_successor_labels() - [e.index]; - dot::LabelText::label(label.clone()) - } -} - -impl dot::GraphWalk<'a> for Formatter<'a, 'tcx, A> -where - A: Analysis<'tcx>, -{ - type Node = BasicBlock; - type Edge = CfgEdge; - - fn nodes(&self) -> dot::Nodes<'_, Self::Node> { - self.body - .basic_blocks() - .indices() - .collect::>() - .into() - } - - fn edges(&self) -> dot::Edges<'_, Self::Edge> { - self.body - .basic_blocks() - .indices() - .flat_map(|bb| outgoing_edges(self.body, bb)) - .collect::>() - .into() - } - - fn source(&self, edge: &Self::Edge) -> Self::Node { - edge.source - } - - fn target(&self, edge: &Self::Edge) -> Self::Node { - self.body - [edge.source] - .terminator() - .successors() - .nth(edge.index) - .copied() - .unwrap() - } -} - -struct BlockFormatter<'a, 'tcx, A> -where - A: Analysis<'tcx>, -{ - prev_state: BitSet, - results: ResultsRefCursor<'a, 'a, 'tcx, A>, - bg: Background, -} - -impl BlockFormatter<'a, 'tcx, A> -where - A: Analysis<'tcx>, -{ - fn toggle_background(&mut self) -> Background { - let bg = self.bg; - self.bg = !bg; - bg - } - - fn write_node_label( - &mut self, - w: &mut impl io::Write, - body: &'a Body<'tcx>, - block: BasicBlock, - ) -> io::Result<()> { - // Sample output: - // +-+-----------------------------------------------+ - // A | bb4 | - // +-+----------------------------------+------------+ - // B | MIR | STATE | - // +-+----------------------------------+------------+ - // C | | (on entry) | {_0,_2,_3} | - // +-+----------------------------------+------------+ - // D |0| StorageLive(_7) | | - // +-+----------------------------------+------------+ - // |1| StorageLive(_8) | | - // +-+----------------------------------+------------+ - // |2| _8 = &mut _1 | +_8 | - // +-+----------------------------------+------------+ - // E |T| _4 = const Foo::twiddle(move _2) | -_2 | - // +-+----------------------------------+------------+ - // F | | (on unwind) | {_0,_3,_8} | - // +-+----------------------------------+------------+ - // | | (on successful return) | +_4 | - // +-+----------------------------------+------------+ - - write!( - w, - r#""#, - )?; - - // A: Block info - write!( - w, - r#" - - "#, - num_headers = 3, - block_id = block.index(), - )?; - - // B: Column headings - write!( - w, - r#" - - - "#, - fmt = r##"bgcolor="#a0a0a0" sides="tl""##, - )?; - - // C: Entry state - self.bg = Background::Light; - self.results.seek_to_block_start(block); - self.write_row_with_curr_state(w, "", "(on entry)")?; - self.prev_state.overwrite(self.results.get()); - - // D: Statement transfer functions - for (i, statement) in body[block].statements.iter().enumerate() { - let location = Location { block, statement_index: i }; - - let mir_col = format!("{:?}", statement); - let i_col = i.to_string(); - - self.results.seek_after(location); - self.write_row_with_curr_diff(w, &i_col, &mir_col)?; - self.prev_state.overwrite(self.results.get()); - } - - // E: Terminator transfer function - let terminator = body[block].terminator(); - let location = body.terminator_loc(block); - - let mut mir_col = String::new(); - terminator.kind.fmt_head(&mut mir_col).unwrap(); - - self.results.seek_after(location); - self.write_row_with_curr_diff(w, "T", &mir_col)?; - self.prev_state.overwrite(self.results.get()); - - // F: Exit state - if let mir::TerminatorKind::Call { destination: Some(_), .. } = &terminator.kind { - self.write_row_with_curr_state(w, "", "(on unwind)")?; - - self.results.seek_after_assume_call_returns(location); - self.write_row_with_curr_diff(w, "", "(on successful return)")?; - } else { - self.write_row_with_curr_state(w, "", "(on exit)")?; - } - - write!(w, "
bb{block_id}
MIRSTATE
") - } - - fn write_row_with_curr_state( - &mut self, - w: &mut impl io::Write, - i: &str, - mir: &str, - ) -> io::Result<()> { - let bg = self.toggle_background(); - - let mut out = Vec::new(); - write!(&mut out, "{{")?; - pretty_print_state_elems(&mut out, self.results.analysis(), self.results.get().iter())?; - write!(&mut out, "}}")?; - - write!( - w, - r#" - {i} - {mir} - {state} - "#, - fmt = &["sides=\"tl\"", bg.attr()].join(" "), - i = i, - mir = dot::escape_html(mir), - state = dot::escape_html(str::from_utf8(&out).unwrap()), - ) - } - - fn write_row_with_curr_diff( - &mut self, - w: &mut impl io::Write, - i: &str, - mir: &str, - ) -> io::Result<()> { - let bg = self.toggle_background(); - let analysis = self.results.analysis(); - - let diff = BitSetDiff::compute(&self.prev_state, self.results.get()); - - let mut set = Vec::new(); - pretty_print_state_elems(&mut set, analysis, diff.set.iter())?; - - let mut clear = Vec::new(); - pretty_print_state_elems(&mut clear, analysis, diff.clear.iter())?; - - write!( - w, - r#" - {i} - {mir} - "#, - i = i, - fmt = &["sides=\"tl\"", bg.attr()].join(" "), - mir = dot::escape_html(mir), - )?; - - if !set.is_empty() { - write!( - w, - r#"+{}"#, - dot::escape_html(str::from_utf8(&set).unwrap()), - )?; - } - - if !set.is_empty() && !clear.is_empty() { - write!(w, " ")?; - } - - if !clear.is_empty() { - write!( - w, - r#"-{}"#, - dot::escape_html(str::from_utf8(&clear).unwrap()), - )?; - } - - write!(w, "") - } -} - -/// The operations required to transform one `BitSet` into another. -struct BitSetDiff { - set: HybridBitSet, - clear: HybridBitSet, -} - -impl BitSetDiff { - fn compute(from: &BitSet, to: &BitSet) -> Self { - assert_eq!(from.domain_size(), to.domain_size()); - let len = from.domain_size(); - - let mut set = HybridBitSet::new_empty(len); - let mut clear = HybridBitSet::new_empty(len); - - // FIXME: This could be made faster if `BitSet::xor` were implemented. - for i in (0..len).map(|i| T::new(i)) { - match (from.contains(i), to.contains(i)) { - (false, true) => set.insert(i), - (true, false) => clear.insert(i), - _ => continue, - }; - } - - BitSetDiff { - set, - clear, - } - } -} - -/// Formats each `elem` using the pretty printer provided by `analysis` into a comma-separated -/// list. -fn pretty_print_state_elems
( - w: &mut impl io::Write, - analysis: &A, - elems: impl Iterator, -) -> io::Result<()> -where - A: Analysis<'tcx>, -{ - let mut first = true; - for idx in elems { - if first { - first = false; - } else { - write!(w, ",")?; - } - - analysis.pretty_print_idx(w, idx)?; - } - - Ok(()) -} - -/// The background color used for zebra-striping the table. -#[derive(Clone, Copy)] -enum Background { - Light, - Dark, -} - -impl Background { - fn attr(self) -> &'static str { - match self { - Self::Dark => "bgcolor=\"#f0f0f0\"", - Self::Light => "", - } - } -} - -impl ops::Not for Background { - type Output = Self; - - fn not(self) -> Self { - match self { - Self::Light => Self::Dark, - Self::Dark => Self::Light, - } - } -} diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 5e64144df2cd1..a86fcb30f4d36 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -5,9 +5,9 @@ use rustc::mir::{self, Location, Place, PlaceBase, Body}; use rustc::ty::{self, TyCtxt}; use rustc::ty::RegionVid; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use crate::dataflow::{BitDenotation, BottomValue, GenKillSet}; use crate::borrow_check::nll::region_infer::RegionInferenceContext; @@ -16,7 +16,7 @@ use crate::borrow_check::places_conflict; use std::rc::Rc; -rustc_index::newtype_index! { +newtype_index! { pub struct BorrowIndex { DEBUG_FORMAT = "bw{}" } diff --git a/src/librustc_mir/dataflow/impls/indirect_mutation.rs b/src/librustc_mir/dataflow/impls/indirect_mutation.rs index bc09e32717926..7d20248ebd1f5 100644 --- a/src/librustc_mir/dataflow/impls/indirect_mutation.rs +++ b/src/librustc_mir/dataflow/impls/indirect_mutation.rs @@ -1,7 +1,7 @@ use rustc::mir::visit::Visitor; use rustc::mir::{self, Local, Location}; use rustc::ty::{self, TyCtxt}; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use syntax_pos::DUMMY_SP; use crate::dataflow::{self, GenKillSet}; @@ -97,27 +97,6 @@ struct TransferFunction<'a, 'mir, 'tcx> { param_env: ty::ParamEnv<'tcx>, } -impl<'tcx> TransferFunction<'_, '_, 'tcx> { - /// Returns `true` if this borrow would allow mutation of the `borrowed_place`. - fn borrow_allows_mutation( - &self, - kind: mir::BorrowKind, - borrowed_place: &mir::Place<'tcx>, - ) -> bool { - match kind { - mir::BorrowKind::Mut { .. } => true, - - | mir::BorrowKind::Shared - | mir::BorrowKind::Shallow - | mir::BorrowKind::Unique - => !borrowed_place - .ty(self.body, self.tcx) - .ty - .is_freeze(self.tcx, self.param_env, DUMMY_SP), - } - } -} - impl<'tcx> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx> { fn visit_rvalue( &mut self, @@ -125,7 +104,21 @@ impl<'tcx> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx> { location: Location, ) { if let mir::Rvalue::Ref(_, kind, ref borrowed_place) = *rvalue { - if self.borrow_allows_mutation(kind, borrowed_place) { + let is_mut = match kind { + mir::BorrowKind::Mut { .. } => true, + + | mir::BorrowKind::Shared + | mir::BorrowKind::Shallow + | mir::BorrowKind::Unique + => { + !borrowed_place + .ty(self.body, self.tcx) + .ty + .is_freeze(self.tcx, self.param_env, DUMMY_SP) + } + }; + + if is_mut { match borrowed_place.base { mir::PlaceBase::Local(borrowed_local) if !borrowed_place.is_indirect() => self.trans.gen(borrowed_local), diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 6f860d00a22c2..d669c786c09df 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -4,8 +4,8 @@ use rustc::ty::TyCtxt; use rustc::mir::{self, Body, Location}; -use rustc_index::bit_set::BitSet; -use rustc_index::vec::Idx; +use rustc_data_structures::bit_set::BitSet; +use rustc_data_structures::indexed_vec::Idx; use super::MoveDataParamEnv; diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 1b81032bfe62f..0f66b13fdc51a 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -109,13 +109,15 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { assert_eq!(1, self.body.arg_count); } - fn before_statement_effect(&self, sets: &mut GenKillSet, loc: Location) { - // If we borrow or assign to a place then it needs storage for that - // statement. + fn statement_effect(&self, + sets: &mut GenKillSet, + loc: Location) { + self.check_for_move(sets, loc); self.check_for_borrow(sets, loc); let stmt = &self.body[loc.block].statements[loc.statement_index]; match stmt.kind { + StatementKind::StorageLive(l) => sets.gen(l), StatementKind::StorageDead(l) => sets.kill(l), StatementKind::Assign(box(ref place, _)) | StatementKind::SetDiscriminant { box ref place, .. } => { @@ -134,37 +136,11 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { } } - fn statement_effect(&self, sets: &mut GenKillSet, loc: Location) { - // If we move from a place then only stops needing storage *after* - // that statement. + fn terminator_effect(&self, + sets: &mut GenKillSet, + loc: Location) { self.check_for_move(sets, loc); - } - - fn before_terminator_effect(&self, sets: &mut GenKillSet, loc: Location) { self.check_for_borrow(sets, loc); - - if let TerminatorKind::Call { - destination: Some((Place { base: PlaceBase::Local(local), .. }, _)), - .. - } = self.body[loc.block].terminator().kind { - sets.gen(local); - } - } - - fn terminator_effect(&self, sets: &mut GenKillSet, loc: Location) { - // For call terminators the destination requires storage for the call - // and after the call returns successfully, but not after a panic. - // Since `propagate_call_unwind` doesn't exist, we have to kill the - // destination here, and then gen it again in `propagate_call_return`. - if let TerminatorKind::Call { - destination: Some((ref place, _)), - .. - } = self.body[loc.block].terminator().kind { - if let Some(local) = place.as_local() { - sets.kill(local); - } - } - self.check_for_move(sets, loc); } fn propagate_call_return( diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index ad0f75d772548..47eb47cf664de 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -1,9 +1,8 @@ use syntax::ast::{self, MetaItem}; -use syntax::print::pprust; use syntax::symbol::{Symbol, sym}; -use rustc_index::bit_set::{BitSet, HybridBitSet}; -use rustc_index::vec::Idx; +use rustc_data_structures::bit_set::{BitSet, HybridBitSet}; +use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::work_queue::WorkQueue; use rustc::hir::def_id::DefId; @@ -160,8 +159,9 @@ where if let Some(s) = item.value_str() { return Some(s.to_string()) } else { - let path = pprust::path_to_string(&item.path); - sess.span_err(item.span, &format!("{} attribute requires a path", path)); + sess.span_err( + item.span, + &format!("{} attribute requires a path", item.path)); return None; } } diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 52016d4c9363a..d9119253cae5f 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -1,7 +1,7 @@ use rustc::mir::tcx::RvalueInitializationState; use rustc::mir::*; use rustc::ty::{self, TyCtxt}; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; @@ -114,7 +114,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { BorrowedContent { target_place: Place { base: place.base.clone(), - projection: tcx.intern_place_elems(proj), + projection: proj.to_vec().into_boxed_slice(), }, }, )); @@ -172,7 +172,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { Some(base), Place { base: place.base.clone(), - projection: tcx.intern_place_elems(proj), + projection: proj.to_vec().into_boxed_slice(), }, ); ent.insert(path); @@ -274,7 +274,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { // Box starts out uninitialized - need to create a separate // move-path for the interior so it will be separate from // the exterior. - self.create_move_path(&self.builder.tcx.mk_place_deref(place.clone())); + self.create_move_path(&place.clone().deref()); self.gather_init(place.as_ref(), InitKind::Shallow); } else { self.gather_init(place.as_ref(), InitKind::Deep); diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index b599f4799446d..156c19c6363e5 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -2,7 +2,7 @@ use core::slice::Iter; use rustc::mir::*; use rustc::ty::{Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; -use rustc_index::vec::{Enumerated, Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Enumerated, Idx, IndexVec}; use smallvec::SmallVec; use syntax_pos::Span; @@ -13,19 +13,19 @@ use self::abs_domain::{AbstractElem, Lift}; mod abs_domain; -rustc_index::newtype_index! { +newtype_index! { pub struct MovePathIndex { DEBUG_FORMAT = "mp{}" } } -rustc_index::newtype_index! { +newtype_index! { pub struct MoveOutIndex { DEBUG_FORMAT = "mo{}" } } -rustc_index::newtype_index! { +newtype_index! { pub struct InitIndex { DEBUG_FORMAT = "in{}" } @@ -327,7 +327,7 @@ impl<'tcx> MoveData<'tcx> { pub fn base_local(&self, mut mpi: MovePathIndex) -> Option { loop { let path = &self.move_paths[mpi]; - if let Some(l) = path.place.as_local() { + if let Place { base: PlaceBase::Local(l), projection: box [] } = path.place { return Some(l); } if let Some(parent) = path.parent { diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index 419c905cb5127..196bcf147f8f8 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -64,9 +64,7 @@ E0004: r##" This error indicates that the compiler cannot guarantee a matching pattern for one or more possible inputs to a match expression. Guaranteed matches are required in order to assign values to match expressions, or alternatively, -determine the flow of execution. - -Erroneous code example: +determine the flow of execution. Erroneous code example: ```compile_fail,E0004 enum Terminator { @@ -111,9 +109,7 @@ match x { E0005: r##" Patterns used to bind names must be irrefutable, that is, they must guarantee -that a name will be extracted in all cases. - -Erroneous code example: +that a name will be extracted in all cases. Erroneous code example: ```compile_fail,E0005 let x = Some(1); @@ -149,8 +145,6 @@ like the following is invalid as it requires the entire `Option` to be moved into a variable called `op_string` while simultaneously requiring the inner `String` to be moved into a variable called `s`. -Erroneous code example: - ```compile_fail,E0007 let x = Some("s".to_string()); @@ -214,130 +208,15 @@ match x { ``` "##, -E0010: r##" -The value of statics and constants must be known at compile time, and they live -for the entire lifetime of a program. Creating a boxed value allocates memory on -the heap at runtime, and therefore cannot be done at compile time. - -Erroneous code example: - -```compile_fail,E0010 -#![feature(box_syntax)] - -const CON : Box = box 0; -``` -"##, - -E0013: r##" -Static and const variables can refer to other const variables. But a const -variable cannot refer to a static variable. - -Erroneous code example: - -```compile_fail,E0013 -static X: i32 = 42; -const Y: i32 = X; -``` - -In this example, `Y` cannot refer to `X` here. To fix this, the value can be -extracted as a const and then used: - -``` -const A: i32 = 42; -static X: i32 = A; -const Y: i32 = A; -``` -"##, - -// FIXME(#57563) Change the language here when const fn stabilizes -E0015: r##" -The only functions that can be called in static or constant expressions are -`const` functions, and struct/enum constructors. `const` functions are only -available on a nightly compiler. Rust currently does not support more general -compile-time function execution. - -``` -const FOO: Option = Some(1); // enum constructor -struct Bar {x: u8} -const BAR: Bar = Bar {x: 1}; // struct constructor -``` - -See [RFC 911] for more details on the design of `const fn`s. - -[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md -"##, - -E0017: r##" -References in statics and constants may only refer to immutable values. - -Erroneous code example: - -```compile_fail,E0017 -static X: i32 = 1; -const C: i32 = 2; - -// these three are not allowed: -const CR: &mut i32 = &mut C; -static STATIC_REF: &'static mut i32 = &mut X; -static CONST_REF: &'static mut i32 = &mut C; -``` - -Statics are shared everywhere, and if they refer to mutable data one might -violate memory safety since holding multiple mutable references to shared data -is not allowed. - -If you really want global mutable state, try using `static mut` or a global -`UnsafeCell`. -"##, - -E0019: r##" -A function call isn't allowed in the const's initialization expression -because the expression's value must be known at compile-time. - -Erroneous code example: - -```compile_fail,E0019 -#![feature(box_syntax)] - -fn main() { - struct MyOwned; - - static STATIC11: Box = box MyOwned; // error! -} -``` - -Remember: you can't use a function call inside a const's initialization -expression! However, you can totally use it anywhere else: - -``` -enum Test { - V1 -} - -impl Test { - fn func(&self) -> i32 { - 12 - } -} - -fn main() { - const FOO: Test = Test::V1; - - FOO.func(); // here is good - let x = FOO.func(); // or even here! -} -``` -"##, - E0030: r##" When matching against a range, the compiler verifies that the range is -non-empty. Range patterns include both end-points, so this is equivalent to +non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range. -Erroneous code example: +For example: -```compile_fail,E0030 +```compile_fail match 5u32 { // This range is ok, albeit pointless. 1 ..= 1 => {} @@ -347,61 +226,7 @@ match 5u32 { ``` "##, -E0133: r##" -Unsafe code was used outside of an unsafe function or block. - -Erroneous code example: - -```compile_fail,E0133 -unsafe fn f() { return; } // This is the unsafe code - -fn main() { - f(); // error: call to unsafe function requires unsafe function or block -} -``` - -Using unsafe functionality is potentially dangerous and disallowed by safety -checks. Examples: - -* Dereferencing raw pointers -* Calling functions via FFI -* Calling functions marked unsafe - -These safety checks can be relaxed for a section of the code by wrapping the -unsafe instructions with an `unsafe` block. For instance: - -``` -unsafe fn f() { return; } - -fn main() { - unsafe { f(); } // ok! -} -``` - -See also https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html -"##, - E0158: r##" -An associated const has been referenced in a pattern. - -Erroneous code example: - -```compile_fail,E0158 -enum EFoo { A, B, C, D } - -trait Foo { - const X: EFoo; -} - -fn test(arg: EFoo) { - match arg { - A::X => { // error! - println!("A::X"); - } - } -} -``` - `const` and `static` mean different things. A `const` is a compile-time constant, an alias for a literal value. This property means you can match it directly within a pattern. @@ -422,39 +247,6 @@ match Some(42) { ``` "##, -E0161: r##" -A value was moved. However, its size was not known at compile time, and only -values of a known size can be moved. - -Erroneous code example: - -```compile_fail,E0161 -#![feature(box_syntax)] - -fn main() { - let array: &[isize] = &[1, 2, 3]; - let _x: Box<[isize]> = box *array; - // error: cannot move a value of type [isize]: the size of [isize] cannot - // be statically determined -} -``` - -In Rust, you can only move a value when its size is known at compile time. - -To work around this restriction, consider "hiding" the value behind a reference: -either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move -it around as usual. Example: - -``` -#![feature(box_syntax)] - -fn main() { - let array: &[isize] = &[1, 2, 3]; - let _x: Box<&[isize]> = box array; // ok! -} -``` -"##, - E0162: r##" #### Note: this error code is no longer emitted by the compiler. @@ -676,6 +468,158 @@ The `op_string_ref` binding has type `&Option<&String>` in both cases. See also https://github.com/rust-lang/rust/issues/14587 "##, +E0010: r##" +The value of statics and constants must be known at compile time, and they live +for the entire lifetime of a program. Creating a boxed value allocates memory on +the heap at runtime, and therefore cannot be done at compile time. Erroneous +code example: + +```compile_fail,E0010 +#![feature(box_syntax)] + +const CON : Box = box 0; +``` +"##, + +E0013: r##" +Static and const variables can refer to other const variables. But a const +variable cannot refer to a static variable. For example, `Y` cannot refer to +`X` here: + +```compile_fail,E0013 +static X: i32 = 42; +const Y: i32 = X; +``` + +To fix this, the value can be extracted as a const and then used: + +``` +const A: i32 = 42; +static X: i32 = A; +const Y: i32 = A; +``` +"##, + +// FIXME(#57563) Change the language here when const fn stabilizes +E0015: r##" +The only functions that can be called in static or constant expressions are +`const` functions, and struct/enum constructors. `const` functions are only +available on a nightly compiler. Rust currently does not support more general +compile-time function execution. + +``` +const FOO: Option = Some(1); // enum constructor +struct Bar {x: u8} +const BAR: Bar = Bar {x: 1}; // struct constructor +``` + +See [RFC 911] for more details on the design of `const fn`s. + +[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md +"##, + +E0017: r##" +References in statics and constants may only refer to immutable values. +Erroneous code example: + +```compile_fail,E0017 +static X: i32 = 1; +const C: i32 = 2; + +// these three are not allowed: +const CR: &mut i32 = &mut C; +static STATIC_REF: &'static mut i32 = &mut X; +static CONST_REF: &'static mut i32 = &mut C; +``` + +Statics are shared everywhere, and if they refer to mutable data one might +violate memory safety since holding multiple mutable references to shared data +is not allowed. + +If you really want global mutable state, try using `static mut` or a global +`UnsafeCell`. +"##, + +E0019: r##" +A function call isn't allowed in the const's initialization expression +because the expression's value must be known at compile-time. Erroneous code +example: + +```compile_fail +enum Test { + V1 +} + +impl Test { + fn test(&self) -> i32 { + 12 + } +} + +fn main() { + const FOO: Test = Test::V1; + + const A: i32 = FOO.test(); // You can't call Test::func() here! +} +``` + +Remember: you can't use a function call inside a const's initialization +expression! However, you can totally use it anywhere else: + +``` +enum Test { + V1 +} + +impl Test { + fn func(&self) -> i32 { + 12 + } +} + +fn main() { + const FOO: Test = Test::V1; + + FOO.func(); // here is good + let x = FOO.func(); // or even here! +} +``` +"##, + +E0133: r##" +Unsafe code was used outside of an unsafe function or block. + +Erroneous code example: + +```compile_fail,E0133 +unsafe fn f() { return; } // This is the unsafe code + +fn main() { + f(); // error: call to unsafe function requires unsafe function or block +} +``` + +Using unsafe functionality is potentially dangerous and disallowed by safety +checks. Examples: + +* Dereferencing raw pointers +* Calling functions via FFI +* Calling functions marked unsafe + +These safety checks can be relaxed for a section of the code by wrapping the +unsafe instructions with an `unsafe` block. For instance: + +``` +unsafe fn f() { return; } + +fn main() { + unsafe { f(); } // ok! +} +``` + +See also https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html +"##, + E0373: r##" This error occurs when an attempt is made to use data captured by a closure, when that data may no longer exist. It's most commonly seen when attempting to @@ -728,9 +672,7 @@ about safety. "##, E0381: r##" -It is not allowed to use or capture an uninitialized variable. - -Erroneous code example: +It is not allowed to use or capture an uninitialized variable. For example: ```compile_fail,E0381 fn main() { @@ -752,9 +694,7 @@ fn main() { E0382: r##" This error occurs when an attempt is made to use a variable after its contents -have been moved elsewhere. - -Erroneous code example: +have been moved elsewhere. For example: ```compile_fail,E0382 struct MyStruct { s: u32 } @@ -902,8 +842,7 @@ x = Foo { a: 2 }; E0384: r##" This error occurs when an attempt is made to reassign an immutable variable. - -Erroneous code example: +For example: ```compile_fail,E0384 fn main() { @@ -923,15 +862,13 @@ fn main() { ``` "##, -E0386: r##" -#### Note: this error code is no longer emitted by the compiler. - +/*E0386: r##" This error occurs when an attempt is made to mutate the target of a mutable reference stored inside an immutable container. For example, this can happen when storing a `&mut` inside an immutable `Box`: -``` +```compile_fail,E0386 let mut x: i64 = 1; let y: Box<_> = Box::new(&mut x); **y = 2; // error, cannot assign to data in an immutable container @@ -955,15 +892,13 @@ let x: i64 = 1; let y: Box> = Box::new(Cell::new(x)); y.set(2); ``` -"##, +"##,*/ E0387: r##" #### Note: this error code is no longer emitted by the compiler. This error occurs when an attempt is made to mutate or mutably reference data -that a closure has captured immutably. - -Erroneous code example: +that a closure has captured immutably. Examples of this error are shown below: ```compile_fail // Accepts a function or a closure that captures its environment immutably. @@ -1018,7 +953,7 @@ https://doc.rust-lang.org/std/cell/ "##, E0388: r##" -#### Note: this error code is no longer emitted by the compiler. +E0388 was removed and is no longer issued. "##, E0389: r##" @@ -1028,7 +963,7 @@ An attempt was made to mutate data using a non-mutable reference. This commonly occurs when attempting to assign to a non-mutable reference of a mutable reference (`&(&mut T)`). -Erroneous code example: +Example of erroneous code: ```compile_fail struct FancyNum { @@ -1087,11 +1022,43 @@ fn main() { ``` "##, -E0492: r##" -A borrow of a constant containing interior mutability was attempted. +E0161: r##" +A value was moved. However, its size was not known at compile time, and only +values of a known size can be moved. Erroneous code example: +```compile_fail +#![feature(box_syntax)] + +fn main() { + let array: &[isize] = &[1, 2, 3]; + let _x: Box<[isize]> = box *array; + // error: cannot move a value of type [isize]: the size of [isize] cannot + // be statically determined +} +``` + +In Rust, you can only move a value when its size is known at compile time. + +To work around this restriction, consider "hiding" the value behind a reference: +either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move +it around as usual. Example: + +``` +#![feature(box_syntax)] + +fn main() { + let array: &[isize] = &[1, 2, 3]; + let _x: Box<&[isize]> = box array; // ok! +} +``` +"##, + +E0492: r##" +A borrow of a constant containing interior mutability was attempted. Erroneous +code example: + ```compile_fail,E0492 use std::sync::atomic::AtomicUsize; @@ -1161,55 +1128,8 @@ Remember this solution is unsafe! You will have to ensure that accesses to the cell are synchronized. "##, -E0493: r##" -A type with a `Drop` implementation was destructured when trying to initialize -a static item. - -Erroneous code example: - -```compile_fail,E0493 -enum DropType { - A, -} - -impl Drop for DropType { - fn drop(&mut self) {} -} - -struct Foo { - field1: DropType, -} - -static FOO: Foo = Foo { ..Foo { field1: DropType::A } }; // error! -``` - -The problem here is that if the given type or one of its fields implements the -`Drop` trait, this `Drop` implementation cannot be called during the static -type initialization which might cause a memory leak. To prevent this issue, -you need to instantiate all the static type's fields by hand. - -``` -enum DropType { - A, -} - -impl Drop for DropType { - fn drop(&mut self) {} -} - -struct Foo { - field1: DropType, -} - -static FOO: Foo = Foo { field1: DropType::A }; // We initialize all fields - // by hand. -``` -"##, - E0499: r##" -A variable was borrowed as mutable more than once. - -Erroneous code example: +A variable was borrowed as mutable more than once. Erroneous code example: ```compile_fail,E0499 let mut i = 0; @@ -1240,9 +1160,7 @@ a; "##, E0500: r##" -A borrowed variable was used by a closure. - -Erroneous code example: +A borrowed variable was used by a closure. Example of erroneous code: ```compile_fail,E0500 fn you_know_nothing(jon_snow: &mut i32) { @@ -1293,7 +1211,7 @@ situation, the closure is borrowing the variable. Take a look at http://rustbyexample.com/fn/closures/capture.html for more information about capturing. -Erroneous code example: +Example of erroneous code: ```compile_fail,E0501 fn inside_closure(x: &mut i32) { @@ -1366,7 +1284,7 @@ E0502: r##" This error indicates that you are trying to borrow a variable as mutable when it has already been borrowed as immutable. -Erroneous code example: +Example of erroneous code: ```compile_fail,E0502 fn bar(x: &mut i32) {} @@ -1397,7 +1315,7 @@ https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html. E0503: r##" A value was used after it was mutably borrowed. -Erroneous code example: +Example of erroneous code: ```compile_fail,E0503 fn main() { @@ -1455,7 +1373,7 @@ E0504: r##" This error occurs when an attempt is made to move a borrowed variable into a closure. -Erroneous code example: +Example of erroneous code: ```compile_fail struct FancyNum { @@ -1646,7 +1564,7 @@ http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html E0506: r##" This error occurs when an attempt is made to assign to a borrowed value. -Erroneous code example: +Example of erroneous code: ```compile_fail,E0506 struct FancyNum { @@ -1864,7 +1782,7 @@ http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html E0508: r##" A value was moved out of a non-copy fixed-size array. -Erroneous code example: +Example of erroneous code: ```compile_fail,E0508 struct NonCopy; @@ -1909,7 +1827,7 @@ E0509: r##" This error occurs when an attempt is made to move out of a value whose type implements the `Drop` trait. -Erroneous code example: +Example of erroneous code: ```compile_fail,E0509 struct FancyNum { @@ -2019,14 +1937,30 @@ Here executing `x = None` would modify the value being matched and require us to go "back in time" to the `None` arm. "##, +E0579: r##" +When matching against an exclusive range, the compiler verifies that the range +is non-empty. Exclusive range patterns include the start point but not the end +point, so this is equivalent to requiring the start of the range to be less +than the end of the range. + +For example: + +```compile_fail +match 5u32 { + // This range is ok, albeit pointless. + 1 .. 2 => {} + // This range is empty, and the compiler can tell. + 5 .. 5 => {} +} +``` +"##, + E0515: r##" Cannot return value that references local variable Local variables, function parameters and temporaries are all dropped before the end of the function body. So a reference to them cannot be returned. -Erroneous code example: - ```compile_fail,E0515 fn get_dangling_reference() -> &'static i32 { let x = 0; @@ -2122,28 +2056,6 @@ fn dragoooon(x: &mut isize) { ``` "##, -E0579: r##" -When matching against an exclusive range, the compiler verifies that the range -is non-empty. Exclusive range patterns include the start point but not the end -point, so this is equivalent to requiring the start of the range to be less -than the end of the range. - -Erroneous code example: - -```compile_fail,E0579 -#![feature(exclusive_range_pattern)] - -fn main() { - match 5u32 { - // This range is ok, albeit pointless. - 1 .. 2 => {} - // This range is empty, and the compiler can tell. - 5 .. 5 => {} // error! - } -} -``` -"##, - E0595: r##" #### Note: this error code is no longer emitted by the compiler. @@ -2167,7 +2079,7 @@ let mut c = || { x += 1 }; E0596: r##" This error occurs because you tried to mutably borrow a non-mutable variable. -Erroneous code example: +Example of erroneous code: ```compile_fail,E0596 let x = 1; @@ -2186,7 +2098,7 @@ let y = &mut x; // ok! E0597: r##" This error occurs because a value was dropped while it was still borrowed -Erroneous code example: +Example of erroneous code: ```compile_fail,E0597 struct Foo<'a> { @@ -2223,8 +2135,6 @@ E0626: r##" This error occurs because a borrow in a generator persists across a yield point. -Erroneous code example: - ```compile_fail,E0626 # #![feature(generators, generator_trait, pin)] # use std::ops::Generator; @@ -2316,7 +2226,7 @@ E0712: r##" This error occurs because a borrow of a thread-local variable was made inside a function which outlived the lifetime of the function. -Erroneous code example: +Example of erroneous code: ```compile_fail,E0712 #![feature(thread_local)] @@ -2338,7 +2248,7 @@ E0713: r##" This error occurs when an attempt is made to borrow state past the end of the lifetime of a type that implements the `Drop` trait. -Erroneous code example: +Example of erroneous code: ```compile_fail,E0713 #![feature(nll)] @@ -2544,6 +2454,7 @@ There are some known bugs that trigger this message. // E0299, // mismatched types between arms // E0471, // constant evaluation error (in pattern) // E0385, // {} in an aliasable location + E0493, // destructors cannot be evaluated at compile-time E0521, // borrowed data escapes outside of closure E0526, // shuffle indices are not constant E0594, // cannot assign to {} diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index e9777dab26e2a..33d67dcf91448 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -5,7 +5,7 @@ use rustc::middle::region; use rustc::hir; use rustc::ty; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { type Output = Block<'tcx>; diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 7bb96661bb746..eed51cdab8c3c 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -3,7 +3,7 @@ use crate::hair::cx::Cx; use crate::hair::cx::block; use crate::hair::cx::to_ref::ToRef; use crate::hair::util::UserAnnotatedTyHelpers; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind}; use rustc::mir::interpret::{GlobalId, ErrorHandled, ConstValue}; use rustc::ty::{self, AdtKind, Ty}; @@ -506,8 +506,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( hir::ExprKind::Closure(..) => { let closure_ty = cx.tables().expr_ty(expr); let (def_id, substs, movability) = match closure_ty.kind { - ty::Closure(def_id, substs) => (def_id, - UpvarSubsts::Closure(substs), None), + ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None), ty::Generator(def_id, substs, movability) => { (def_id, UpvarSubsts::Generator(substs), Some(movability)) } @@ -908,7 +907,7 @@ fn convert_path_expr<'a, 'tcx>( let generics = cx.tcx.generics_of(item_def_id); let local_def_id = cx.tcx.hir().local_def_id(hir_id); let index = generics.param_def_id_to_index[&local_def_id]; - let name = cx.tcx.hir().name(hir_id); + let name = cx.tcx.hir().name(hir_id).as_interned_str(); let val = ConstValue::Param(ty::ParamConst::new(index, name)); ExprKind::Literal { literal: cx.tcx.mk_const( @@ -1012,7 +1011,7 @@ fn convert_var( }); Expr { ty: closure_ty, - temp_lifetime, + temp_lifetime: temp_lifetime, span: expr.span, kind: ExprKind::Deref { arg: Expr { diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index e120b496d3d09..32efbd6f01173 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -5,7 +5,7 @@ use crate::hair::*; use crate::hair::util::UserAnnotatedTyHelpers; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use rustc::hir::def_id::DefId; use rustc::hir::Node; use rustc::middle::region; diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 907c84b6f8cf0..75a84f6ec648b 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -161,20 +161,19 @@ use self::Usefulness::*; use self::WitnessPreference::*; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use super::{FieldPat, Pat, PatKind, PatRange}; use super::{PatternFoldable, PatternFolder, compare_const_vals}; use rustc::hir::def_id::DefId; -use rustc::hir::{RangeEnd, HirId}; +use rustc::hir::RangeEnd; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const}; use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size}; use rustc::mir::Field; use rustc::mir::interpret::{ConstValue, Scalar, truncate, AllocId, Pointer}; use rustc::util::common::ErrorReported; -use rustc::lint; use syntax::attr::{SignedInt, UnsignedInt}; use syntax_pos::{Span, DUMMY_SP}; @@ -189,8 +188,8 @@ use std::ops::RangeInclusive; use std::u128; use std::convert::TryInto; -pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pat<'tcx>) -> Pat<'tcx> { - LiteralExpander { tcx: cx.tcx }.fold_pattern(&pat) +pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pat<'tcx>) -> &'a Pat<'tcx> { + cx.pattern_arena.alloc(LiteralExpander { tcx: cx.tcx }.fold_pattern(&pat)) } struct LiteralExpander<'tcx> { @@ -394,6 +393,16 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { } } + fn is_non_exhaustive_variant<'p>(&self, pattern: &'p Pat<'tcx>) -> bool { + match *pattern.kind { + PatKind::Variant { adt_def, variant_index, .. } => { + let ref variant = adt_def.variants[variant_index]; + variant.is_field_list_non_exhaustive() + } + _ => false, + } + } + fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool { match ty.kind { ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(), @@ -409,7 +418,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] enum Constructor<'tcx> { /// The constructor of all patterns that don't vary by constructor, /// e.g., struct patterns and fixed-length arrays. @@ -417,71 +426,29 @@ enum Constructor<'tcx> { /// Enum variants. Variant(DefId), /// Literal values. - ConstantValue(&'tcx ty::Const<'tcx>, Span), + ConstantValue(&'tcx ty::Const<'tcx>), /// Ranges of literal values (`2..=5` and `2..5`). - ConstantRange(u128, u128, Ty<'tcx>, RangeEnd, Span), + ConstantRange(u128, u128, Ty<'tcx>, RangeEnd), /// Array patterns of length n. Slice(u64), } -// Ignore spans when comparing, they don't carry semantic information as they are only for lints. -impl<'tcx> std::cmp::PartialEq for Constructor<'tcx> { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Constructor::Single, Constructor::Single) => true, - (Constructor::Variant(a), Constructor::Variant(b)) => a == b, - (Constructor::ConstantValue(a, _), Constructor::ConstantValue(b, _)) => a == b, - ( - Constructor::ConstantRange(a_start, a_end, a_ty, a_range_end, _), - Constructor::ConstantRange(b_start, b_end, b_ty, b_range_end, _), - ) => a_start == b_start && a_end == b_end && a_ty == b_ty && a_range_end == b_range_end, - (Constructor::Slice(a), Constructor::Slice(b)) => a == b, - _ => false, - } - } -} - impl<'tcx> Constructor<'tcx> { - fn is_slice(&self) -> bool { - match self { - Slice { .. } => true, - _ => false, - } - } - fn variant_index_for_adt<'a>( &self, cx: &MatchCheckCtxt<'a, 'tcx>, adt: &'tcx ty::AdtDef, ) -> VariantIdx { match self { - Variant(id) => adt.variant_index_with_id(*id), - Single => { + &Variant(id) => adt.variant_index_with_id(id), + &Single => { assert!(!adt.is_enum()); VariantIdx::new(0) } - ConstantValue(c, _) => crate::const_eval::const_variant_index(cx.tcx, cx.param_env, c), + &ConstantValue(c) => crate::const_eval::const_variant_index(cx.tcx, cx.param_env, c), _ => bug!("bad constructor {:?} for adt {:?}", self, adt) } } - - fn display(&self, tcx: TyCtxt<'tcx>) -> String { - match self { - Constructor::ConstantValue(val, _) => format!("{}", val), - Constructor::ConstantRange(lo, hi, ty, range_end, _) => { - // Get the right sign on the output: - let ty = ty::ParamEnv::empty().and(*ty); - format!( - "{}{}{}", - ty::Const::from_bits(tcx, *lo, ty), - range_end, - ty::Const::from_bits(tcx, *hi, ty), - ) - } - Constructor::Slice(val) => format!("[{}]", val), - _ => bug!("bad constructor being displayed: `{:?}", self), - } - } } #[derive(Clone, Debug)] @@ -510,7 +477,6 @@ pub enum WitnessPreference { struct PatCtxt<'tcx> { ty: Ty<'tcx>, max_slice_length: u64, - span: Span, } /// A witness of non-exhaustiveness for error reporting, represented @@ -637,8 +603,8 @@ impl<'tcx> Witness<'tcx> { _ => { match *ctor { - ConstantValue(value, _) => PatKind::Constant { value }, - ConstantRange(lo, hi, ty, end, _) => PatKind::Range(PatRange { + ConstantValue(value) => PatKind::Constant { value }, + ConstantRange(lo, hi, ty, end) => PatKind::Range(PatRange { 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)), end, @@ -674,7 +640,7 @@ fn all_constructors<'a, 'tcx>( let ctors = match pcx.ty.kind { ty::Bool => { [true, false].iter().map(|&b| { - ConstantValue(ty::Const::from_bool(cx.tcx, b), pcx.span) + ConstantValue(ty::Const::from_bool(cx.tcx, b)) }).collect() } ty::Array(ref sub_ty, len) if len.try_eval_usize(cx.tcx, cx.param_env).is_some() => { @@ -706,19 +672,15 @@ fn all_constructors<'a, 'tcx>( ty::Char => { vec![ // The valid Unicode Scalar Value ranges. - ConstantRange( - '\u{0000}' as u128, - '\u{D7FF}' as u128, - cx.tcx.types.char, - RangeEnd::Included, - pcx.span, + ConstantRange('\u{0000}' as u128, + '\u{D7FF}' as u128, + cx.tcx.types.char, + RangeEnd::Included ), - ConstantRange( - '\u{E000}' as u128, - '\u{10FFFF}' as u128, - cx.tcx.types.char, - RangeEnd::Included, - pcx.span, + ConstantRange('\u{E000}' as u128, + '\u{10FFFF}' as u128, + cx.tcx.types.char, + RangeEnd::Included ), ] } @@ -726,12 +688,12 @@ fn all_constructors<'a, 'tcx>( let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128; let min = 1u128 << (bits - 1); let max = min - 1; - vec![ConstantRange(min, max, pcx.ty, RangeEnd::Included, pcx.span)] + vec![ConstantRange(min, max, pcx.ty, RangeEnd::Included)] } ty::Uint(uty) => { let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size(); let max = truncate(u128::max_value(), size); - vec![ConstantRange(0, max, pcx.ty, RangeEnd::Included, pcx.span)] + vec![ConstantRange(0, max, pcx.ty, RangeEnd::Included)] } _ => { if cx.is_uninhabited(pcx.ty) { @@ -858,90 +820,13 @@ where /// /// `IntRange` is never used to encode an empty range or a "range" that wraps /// around the (offset) space: i.e., `range.lo <= range.hi`. -#[derive(Clone, Debug)] +#[derive(Clone)] struct IntRange<'tcx> { pub range: RangeInclusive, pub ty: Ty<'tcx>, - pub span: Span, } impl<'tcx> IntRange<'tcx> { - #[inline] - fn is_integral(ty: Ty<'_>) -> bool { - match ty.kind { - ty::Char | ty::Int(_) | ty::Uint(_) => true, - _ => false, - } - } - - #[inline] - fn integral_size_and_signed_bias(tcx: TyCtxt<'tcx>, ty: Ty<'_>) -> Option<(Size, u128)> { - match ty.kind { - ty::Char => Some((Size::from_bytes(4), 0)), - ty::Int(ity) => { - let size = Integer::from_attr(&tcx, SignedInt(ity)).size(); - Some((size, 1u128 << (size.bits() as u128 - 1))) - } - ty::Uint(uty) => Some((Integer::from_attr(&tcx, UnsignedInt(uty)).size(), 0)), - _ => None, - } - } - - #[inline] - fn from_const( - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - value: &Const<'tcx>, - span: Span, - ) -> Option> { - if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, value.ty) { - let ty = value.ty; - let val = if let ConstValue::Scalar(Scalar::Raw { data, size }) = value.val { - // For this specific pattern we can skip a lot of effort and go - // straight to the result, after doing a bit of checking. (We - // could remove this branch and just use the next branch, which - // is more general but much slower.) - Scalar::<()>::check_raw(data, size, target_size); - data - } else if let Some(val) = value.try_eval_bits(tcx, param_env, ty) { - // This is a more general form of the previous branch. - val - } else { - return None - }; - let val = val ^ bias; - Some(IntRange { range: val..=val, ty, span }) - } else { - None - } - } - - #[inline] - fn from_range( - tcx: TyCtxt<'tcx>, - lo: u128, - hi: u128, - ty: Ty<'tcx>, - end: &RangeEnd, - span: Span, - ) -> Option> { - if Self::is_integral(ty) { - // Perform a shift if the underlying types are signed, - // which makes the interval arithmetic simpler. - let bias = IntRange::signed_bias(tcx, ty); - let (lo, hi) = (lo ^ bias, hi ^ bias); - // Make sure the interval is well-formed. - if lo > hi || lo == hi && *end == RangeEnd::Excluded { - None - } else { - let offset = (*end == RangeEnd::Excluded) as u128; - Some(IntRange { range: lo..=(hi - offset), ty, span }) - } - } else { - None - } - } - fn from_ctor( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -949,9 +834,37 @@ impl<'tcx> IntRange<'tcx> { ) -> Option> { // Floating-point ranges are permitted and we don't want // to consider them when constructing integer ranges. + fn is_integral(ty: Ty<'_>) -> bool { + match ty.kind { + ty::Char | ty::Int(_) | ty::Uint(_) => true, + _ => false, + } + } + match ctor { - ConstantRange(lo, hi, ty, end, span) => Self::from_range(tcx, *lo, *hi, ty, end, *span), - ConstantValue(val, span) => Self::from_const(tcx, param_env, val, *span), + ConstantRange(lo, hi, ty, end) if is_integral(ty) => { + // Perform a shift if the underlying types are signed, + // which makes the interval arithmetic simpler. + let bias = IntRange::signed_bias(tcx, ty); + let (lo, hi) = (lo ^ bias, hi ^ bias); + // Make sure the interval is well-formed. + if lo > hi || lo == hi && *end == RangeEnd::Excluded { + None + } else { + let offset = (*end == RangeEnd::Excluded) as u128; + Some(IntRange { range: lo..=(hi - offset), ty }) + } + } + ConstantValue(val) if is_integral(val.ty) => { + let ty = val.ty; + if let Some(val) = val.try_eval_bits(tcx, param_env, ty) { + let bias = IntRange::signed_bias(tcx, ty); + let val = val ^ bias; + Some(IntRange { range: val..=val, ty }) + } else { + None + } + } _ => None, } } @@ -961,27 +874,22 @@ impl<'tcx> IntRange<'tcx> { param_env: ty::ParamEnv<'tcx>, mut pat: &Pat<'tcx>, ) -> Option> { - loop { + let range = loop { match pat.kind { - box PatKind::Constant { value } => { - return Self::from_const(tcx, param_env, value, pat.span); - } - box PatKind::Range(PatRange { lo, hi, end }) => { - return Self::from_range( - tcx, - lo.eval_bits(tcx, param_env, lo.ty), - hi.eval_bits(tcx, param_env, hi.ty), - &lo.ty, - &end, - pat.span, - ); - } + box PatKind::Constant { value } => break ConstantValue(value), + box PatKind::Range(PatRange { 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 PatKind::AscribeUserType { ref subpattern, .. } => { pat = subpattern; }, _ => return None, } - } + }; + Self::from_ctor(tcx, param_env, &range) } // The return value of `signed_bias` should be XORed with an endpoint to encode/decode it. @@ -1000,15 +908,14 @@ impl<'tcx> IntRange<'tcx> { tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, r: RangeInclusive, - span: Span, ) -> Constructor<'tcx> { let bias = IntRange::signed_bias(tcx, ty); let (lo, hi) = r.into_inner(); if lo == hi { let ty = ty::ParamEnv::empty().and(ty); - ConstantValue(ty::Const::from_bits(tcx, lo ^ bias, ty), span) + ConstantValue(ty::Const::from_bits(tcx, lo ^ bias, ty)) } else { - ConstantRange(lo ^ bias, hi ^ bias, ty, RangeEnd::Included, span) + ConstantRange(lo ^ bias, hi ^ bias, ty, RangeEnd::Included) } } @@ -1031,23 +938,17 @@ impl<'tcx> IntRange<'tcx> { if lo > subrange_hi || subrange_lo > hi { // The pattern doesn't intersect with the subrange at all, // so the subrange remains untouched. - remaining_ranges.push( - Self::range_to_ctor(tcx, ty, subrange_lo..=subrange_hi, self.span), - ); + remaining_ranges.push(Self::range_to_ctor(tcx, ty, subrange_lo..=subrange_hi)); } else { if lo > subrange_lo { // The pattern intersects an upper section of the // subrange, so a lower section will remain. - remaining_ranges.push( - Self::range_to_ctor(tcx, ty, subrange_lo..=(lo - 1), self.span), - ); + remaining_ranges.push(Self::range_to_ctor(tcx, ty, subrange_lo..=(lo - 1))); } if hi < subrange_hi { // The pattern intersects a lower section of the // subrange, so an upper section will remain. - remaining_ranges.push( - Self::range_to_ctor(tcx, ty, (hi + 1)..=subrange_hi, self.span), - ); + remaining_ranges.push(Self::range_to_ctor(tcx, ty, (hi + 1)..=subrange_hi)); } } } @@ -1059,29 +960,11 @@ impl<'tcx> IntRange<'tcx> { let (lo, hi) = (*self.range.start(), *self.range.end()); let (other_lo, other_hi) = (*other.range.start(), *other.range.end()); if lo <= other_hi && other_lo <= hi { - let span = other.span; - Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty, span }) + Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty }) } else { None } } - - fn suspicious_intersection(&self, other: &Self) -> bool { - // `false` in the following cases: - // 1 ---- // 1 ---------- // 1 ---- // 1 ---- - // 2 ---------- // 2 ---- // 2 ---- // 2 ---- - // - // The following are currently `false`, but could be `true` in the future (#64007): - // 1 --------- // 1 --------- - // 2 ---------- // 2 ---------- - // - // `true` in the following cases: - // 1 ------- // 1 ------- - // 2 -------- // 2 ------- - let (lo, hi) = (*self.range.start(), *self.range.end()); - let (other_lo, other_hi) = (*other.range.start(), *other.range.end()); - (lo == other_hi || hi == other_lo) - } } // A request for missing constructor data in terms of either: @@ -1187,7 +1070,6 @@ pub fn is_useful<'p, 'a, 'tcx>( matrix: &Matrix<'p, 'tcx>, v: &[&Pat<'tcx>], witness: WitnessPreference, - hir_id: HirId, ) -> Usefulness<'tcx> { let &Matrix(ref rows) = matrix; debug!("is_useful({:#?}, {:#?})", matrix, v); @@ -1210,10 +1092,6 @@ pub fn is_useful<'p, 'a, 'tcx>( assert!(rows.iter().all(|r| r.len() == v.len())); - let (ty, span) = rows.iter() - .map(|r| (r[0].ty, r[0].span)) - .find(|(ty, _)| !ty.references_error()) - .unwrap_or((v[0].ty, v[0].span)); let pcx = PatCtxt { // TyErr is used to represent the type of wildcard patterns matching // against inaccessible (private) fields of structs, so that we won't @@ -1234,20 +1112,26 @@ pub fn is_useful<'p, 'a, 'tcx>( // FIXME: this might lead to "unstable" behavior with macro hygiene // introducing uninhabited patterns for inaccessible fields. We // need to figure out how to model that. - ty, - max_slice_length: max_slice_length(cx, rows.iter().map(|r| r[0]).chain(Some(v[0]))), - span, + ty: rows.iter().map(|r| r[0].ty).find(|ty| !ty.references_error()).unwrap_or(v[0].ty), + max_slice_length: max_slice_length(cx, rows.iter().map(|r| r[0]).chain(Some(v[0]))) }; debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v[0]); if let Some(constructors) = pat_constructors(cx, v[0], pcx) { - debug!("is_useful - expanding constructors: {:#?}", constructors); - split_grouped_constructors( - cx.tcx, cx.param_env, constructors, matrix, pcx.ty, pcx.span, Some(hir_id), - ).into_iter().map(|c| - is_useful_specialized(cx, matrix, v, c, pcx.ty, witness, hir_id) - ).find(|result| result.is_useful()).unwrap_or(NotUseful) + let is_declared_nonexhaustive = cx.is_non_exhaustive_variant(v[0]) && !cx.is_local(pcx.ty); + debug!("is_useful - expanding constructors: {:#?}, is_declared_nonexhaustive: {:?}", + constructors, is_declared_nonexhaustive); + + if is_declared_nonexhaustive { + Useful + } else { + split_grouped_constructors( + cx.tcx, cx.param_env, constructors, matrix, pcx.ty, + ).into_iter().map(|c| + is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) + ).find(|result| result.is_useful()).unwrap_or(NotUseful) + } } else { debug!("is_useful - expanding wildcard"); @@ -1298,11 +1182,8 @@ pub fn is_useful<'p, 'a, 'tcx>( (pcx.ty.is_ptr_sized_integral() && !cx.tcx.features().precise_pointer_size_matching); if cheap_missing_ctors == MissingCtors::Empty && !is_non_exhaustive { - split_grouped_constructors( - cx.tcx, cx.param_env, all_ctors, matrix, pcx.ty, DUMMY_SP, None, - ) - .into_iter() - .map(|c| is_useful_specialized(cx, matrix, v, c, pcx.ty, witness, hir_id)) + split_grouped_constructors(cx.tcx, cx.param_env, all_ctors, matrix, pcx.ty) + .into_iter().map(|c| is_useful_specialized(cx, matrix, v, c, pcx.ty, witness)) .find(|result| result.is_useful()) .unwrap_or(NotUseful) } else { @@ -1313,7 +1194,7 @@ pub fn is_useful<'p, 'a, 'tcx>( None } }).collect(); - match is_useful(cx, &matrix, &v[1..], witness, hir_id) { + match is_useful(cx, &matrix, &v[1..], witness) { UsefulWithWitness(pats) => { let cx = &*cx; // In this case, there's at least one "free" @@ -1406,7 +1287,6 @@ fn is_useful_specialized<'p, 'a, 'tcx>( ctor: Constructor<'tcx>, lty: Ty<'tcx>, witness: WitnessPreference, - hir_id: HirId, ) -> Usefulness<'tcx> { debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty); let sub_pat_tys = constructor_sub_pattern_tys(cx, &ctor, lty); @@ -1418,13 +1298,11 @@ fn is_useful_specialized<'p, 'a, 'tcx>( } }).collect(); let wild_patterns: Vec<_> = wild_patterns_owned.iter().collect(); - let matrix = Matrix( - m.iter() - .filter_map(|r| specialize(cx, &r, &ctor, &wild_patterns)) - .collect() - ); + let matrix = Matrix(m.iter().flat_map(|r| { + specialize(cx, &r, &ctor, &wild_patterns) + }).collect()); match specialize(cx, v, &ctor, &wild_patterns) { - Some(v) => match is_useful(cx, &matrix, &v, witness, hir_id) { + Some(v) => match is_useful(cx, &matrix, &v, witness) { UsefulWithWitness(witnesses) => UsefulWithWitness( witnesses.into_iter() .map(|witness| witness.apply_constructor(cx, &ctor, lty)) @@ -1444,11 +1322,11 @@ fn is_useful_specialized<'p, 'a, 'tcx>( /// `[a, b, ..tail]` can match a slice of length 2, 3, 4 and so on. /// /// Returns `None` in case of a catch-all, which can't be specialized. -fn pat_constructors<'tcx>( - cx: &mut MatchCheckCtxt<'_, 'tcx>, - pat: &Pat<'tcx>, - pcx: PatCtxt<'tcx>, -) -> Option>> { +fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, + pat: &Pat<'tcx>, + pcx: PatCtxt<'tcx>) + -> Option>> +{ match *pat.kind { PatKind::AscribeUserType { ref subpattern, .. } => pat_constructors(cx, subpattern, pcx), @@ -1457,14 +1335,13 @@ fn pat_constructors<'tcx>( PatKind::Variant { adt_def, variant_index, .. } => { Some(vec![Variant(adt_def.variants[variant_index].def_id)]) } - PatKind::Constant { value } => Some(vec![ConstantValue(value, pat.span)]), + PatKind::Constant { value } => Some(vec![ConstantValue(value)]), PatKind::Range(PatRange { lo, hi, end }) => Some(vec![ConstantRange( lo.eval_bits(cx.tcx, cx.param_env, lo.ty), hi.eval_bits(cx.tcx, cx.param_env, hi.ty), lo.ty, end, - pat.span, )]), PatKind::Array { .. } => match pcx.ty.kind { ty::Array(_, length) => Some(vec![ @@ -1497,7 +1374,7 @@ fn constructor_arity(cx: &MatchCheckCtxt<'a, 'tcx>, ctor: &Constructor<'tcx>, ty ty::Tuple(ref fs) => fs.len() as u64, ty::Slice(..) | ty::Array(..) => match *ctor { Slice(length) => length, - ConstantValue(..) => 0, + ConstantValue(_) => 0, _ => bug!("bad slice pattern {:?} {:?}", ctor, ty) } ty::Ref(..) => 1, @@ -1522,7 +1399,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx>( ty::Tuple(ref fs) => fs.into_iter().map(|t| t.expect_ty()).collect(), ty::Slice(ty) | ty::Array(ty, _) => match *ctor { Slice(length) => (0..length).map(|_| ty).collect(), - ConstantValue(..) => vec![], + ConstantValue(_) => vec![], _ => bug!("bad slice pattern {:?} {:?}", ctor, ty) } ty::Ref(_, rty, _) => vec![rty], @@ -1531,30 +1408,27 @@ fn constructor_sub_pattern_tys<'a, 'tcx>( // Use T as the sub pattern type of Box. vec![substs.type_at(0)] } else { - let variant = &adt.variants[ctor.variant_index_for_adt(cx, adt)]; - let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !cx.is_local(ty); - variant.fields.iter().map(|field| { + adt.variants[ctor.variant_index_for_adt(cx, adt)].fields.iter().map(|field| { let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); - let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs)); - match (is_visible, is_non_exhaustive, is_uninhabited) { - // Treat all uninhabited types in non-exhaustive variants as `TyErr`. - (_, true, true) => cx.tcx.types.err, - // Treat all non-visible fields as `TyErr`. They can't appear in any - // other pattern from this match (because they are private), so their - // type does not matter - but we don't want to know they are uninhabited. - (false, ..) => cx.tcx.types.err, - (true, ..) => { - let ty = field.ty(cx.tcx, substs); - match ty.kind { - // If the field type returned is an array of an unknown - // size return an TyErr. - ty::Array(_, len) - if len.try_eval_usize(cx.tcx, cx.param_env).is_none() => - cx.tcx.types.err, - _ => ty, - } - }, + if is_visible { + let ty = field.ty(cx.tcx, substs); + match ty.kind { + // If the field type returned is an array of an unknown + // size return an TyErr. + ty::Array(_, len) + if len.try_eval_usize(cx.tcx, cx.param_env).is_none() => + cx.tcx.types.err, + _ => ty, + } + } else { + // Treat all non-visible fields as TyErr. They + // can't appear in any other pattern from + // this match (because they are private), + // so their type does not matter - but + // we don't want to know they are + // uninhabited. + cx.tcx.types.err } }).collect() } @@ -1623,8 +1497,8 @@ fn slice_pat_covered_by_const<'tcx>( // constructor is a range or constant with an integer type. fn should_treat_range_exhaustively(tcx: TyCtxt<'tcx>, ctor: &Constructor<'tcx>) -> bool { let ty = match ctor { - ConstantValue(value, _) => value.ty, - ConstantRange(_, _, ty, _, _) => ty, + ConstantValue(value) => value.ty, + ConstantRange(_, _, ty, _) => ty, _ => return false, }; if let ty::Char | ty::Int(_) | ty::Uint(_) = ty.kind { @@ -1666,17 +1540,12 @@ fn should_treat_range_exhaustively(tcx: TyCtxt<'tcx>, ctor: &Constructor<'tcx>) /// boundaries for each interval range, sort them, then create constructors for each new interval /// between every pair of boundary points. (This essentially sums up to performing the intuitive /// merging operation depicted above.) -/// -/// `hir_id` is `None` when we're evaluating the wildcard pattern, do not lint for overlapping in -/// ranges that case. fn split_grouped_constructors<'p, 'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ctors: Vec>, &Matrix(ref m): &Matrix<'p, 'tcx>, ty: Ty<'tcx>, - span: Span, - hir_id: Option, ) -> Vec> { let mut split_ctors = Vec::with_capacity(ctors.len()); @@ -1693,7 +1562,7 @@ fn split_grouped_constructors<'p, 'tcx>( /// Represents a border between 2 integers. Because the intervals spanning borders /// must be able to cover every integer, we need to be able to represent /// 2^128 + 1 such borders. - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] enum Border { JustBefore(u128), AfterMax, @@ -1710,38 +1579,16 @@ fn split_grouped_constructors<'p, 'tcx>( vec![from, to].into_iter() } - // Collect the span and range of all the intersecting ranges to lint on likely - // incorrect range patterns. (#63987) - let mut overlaps = vec![]; // `borders` is the set of borders between equivalence classes: each equivalence // class lies between 2 borders. let row_borders = m.iter() - .flat_map(|row| { - IntRange::from_pat(tcx, param_env, row[0]).map(|r| (r, row.len())) - }) - .flat_map(|(range, row_len)| { - let intersection = ctor_range.intersection(&range); - let should_lint = ctor_range.suspicious_intersection(&range); - if let (Some(range), 1, true) = (&intersection, row_len, should_lint) { - // FIXME: for now, only check for overlapping ranges on simple range - // patterns. Otherwise with the current logic the following is detected - // as overlapping: - // match (10u8, true) { - // (0 ..= 125, false) => {} - // (126 ..= 255, false) => {} - // (0 ..= 255, true) => {} - // } - overlaps.push(range.clone()); - } - intersection - }) + .flat_map(|row| IntRange::from_pat(tcx, param_env, row[0])) + .flat_map(|range| ctor_range.intersection(&range)) .flat_map(|range| range_borders(range)); let ctor_borders = range_borders(ctor_range.clone()); let mut borders: Vec<_> = row_borders.chain(ctor_borders).collect(); borders.sort_unstable(); - lint_overlapping_patterns(tcx, hir_id, ctor_range, ty, overlaps); - // We're going to iterate through every pair of borders, making sure that each // represents an interval of nonnegative length, and convert each such interval // into a constructor. @@ -1749,18 +1596,18 @@ fn split_grouped_constructors<'p, 'tcx>( match (window[0], window[1]) { (Border::JustBefore(n), Border::JustBefore(m)) => { if n < m { - Some(IntRange { range: n..=(m - 1), ty, span }) + Some(IntRange { range: n..=(m - 1), ty }) } else { None } } (Border::JustBefore(n), Border::AfterMax) => { - Some(IntRange { range: n..=u128::MAX, ty, span }) + Some(IntRange { range: n..=u128::MAX, ty }) } (Border::AfterMax, _) => None, } }) { - split_ctors.push(IntRange::range_to_ctor(tcx, ty, range, span)); + split_ctors.push(IntRange::range_to_ctor(tcx, ty, range)); } } // Any other constructor can be used unchanged. @@ -1771,29 +1618,33 @@ fn split_grouped_constructors<'p, 'tcx>( split_ctors } -fn lint_overlapping_patterns( +/// Checks whether there exists any shared value in either `ctor` or `pat` by intersecting them. +fn constructor_intersects_pattern<'p, 'tcx>( tcx: TyCtxt<'tcx>, - hir_id: Option, - ctor_range: IntRange<'tcx>, - ty: Ty<'tcx>, - overlaps: Vec>, -) { - if let (true, Some(hir_id)) = (!overlaps.is_empty(), hir_id) { - let mut err = tcx.struct_span_lint_hir( - lint::builtin::OVERLAPPING_PATTERNS, - hir_id, - ctor_range.span, - "multiple patterns covering the same range", - ); - err.span_label(ctor_range.span, "overlapping patterns"); - for int_range in overlaps { - // Use the real type for user display of the ranges: - err.span_label(int_range.span, &format!( - "this range overlaps on `{}`", - IntRange::range_to_ctor(tcx, ty, int_range.range, DUMMY_SP).display(tcx), - )); + param_env: ty::ParamEnv<'tcx>, + ctor: &Constructor<'tcx>, + pat: &'p Pat<'tcx>, +) -> Option; 2]>> { + if should_treat_range_exhaustively(tcx, ctor) { + match (IntRange::from_ctor(tcx, param_env, ctor), IntRange::from_pat(tcx, param_env, pat)) { + (Some(ctor), Some(pat)) => { + ctor.intersection(&pat).map(|_| { + let (pat_lo, pat_hi) = pat.range.into_inner(); + let (ctor_lo, ctor_hi) = ctor.range.into_inner(); + assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi); + smallvec![] + }) + } + _ => None, + } + } else { + // Fallback for non-ranges and ranges that involve floating-point numbers, which are not + // conveniently handled by `IntRange`. For these cases, the constructor may not be a range + // so intersection actually devolves into being covered by the pattern. + match constructor_covered_by_range(tcx, param_env, ctor, pat) { + Ok(true) => Some(smallvec![]), + Ok(false) | Err(ErrorReported) => None, } - err.emit(); } } @@ -1821,13 +1672,13 @@ fn constructor_covered_by_range<'tcx>( }; } match *ctor { - ConstantValue(value, _) => { + ConstantValue(value) => { let to = some_or_ok!(cmp_to(value)); let end = (to == Ordering::Less) || (end == RangeEnd::Included && to == Ordering::Equal); Ok(some_or_ok!(cmp_from(value)) && end) }, - ConstantRange(from, to, ty, RangeEnd::Included, _) => { + ConstantRange(from, to, ty, RangeEnd::Included) => { let to = some_or_ok!(cmp_to(ty::Const::from_bits( tcx, to, @@ -1841,7 +1692,7 @@ fn constructor_covered_by_range<'tcx>( ty::ParamEnv::empty().and(ty), ))) && end) }, - ConstantRange(from, to, ty, RangeEnd::Excluded, _) => { + ConstantRange(from, to, ty, RangeEnd::Excluded) => { let to = some_or_ok!(cmp_to(ty::Const::from_bits( tcx, to, @@ -1860,18 +1711,15 @@ fn constructor_covered_by_range<'tcx>( } } -fn patterns_for_variant<'p, 'a: 'p, 'tcx>( - cx: &mut MatchCheckCtxt<'a, 'tcx>, +fn patterns_for_variant<'p, 'tcx>( subpatterns: &'p [FieldPat<'tcx>], - wild_patterns: &[&'p Pat<'tcx>], - is_non_exhaustive: bool, -) -> SmallVec<[&'p Pat<'tcx>; 2]> { + wild_patterns: &[&'p Pat<'tcx>]) + -> SmallVec<[&'p Pat<'tcx>; 2]> +{ let mut result = SmallVec::from_slice(wild_patterns); for subpat in subpatterns { - if !is_non_exhaustive || !cx.is_uninhabited(subpat.pattern.ty) { - result[subpat.field.index()] = &subpat.pattern; - } + result[subpat.field.index()] = &subpat.pattern; } debug!("patterns_for_variant({:#?}, {:#?}) = {:#?}", subpatterns, wild_patterns, result); @@ -1905,118 +1753,103 @@ fn specialize<'p, 'a: 'p, 'tcx>( PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => { let ref variant = adt_def.variants[variant_index]; - let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !cx.is_local(pat.ty); Some(Variant(variant.def_id)) .filter(|variant_constructor| variant_constructor == constructor) - .map(|_| patterns_for_variant(cx, subpatterns, wild_patterns, is_non_exhaustive)) + .map(|_| patterns_for_variant(subpatterns, wild_patterns)) } PatKind::Leaf { ref subpatterns } => { - Some(patterns_for_variant(cx, subpatterns, wild_patterns, false)) + Some(patterns_for_variant(subpatterns, wild_patterns)) } PatKind::Deref { ref subpattern } => { Some(smallvec![subpattern]) } - PatKind::Constant { value } if constructor.is_slice() => { - // We extract an `Option` for the pointer because slices of zero - // elements don't necessarily point to memory, they are usually - // just integers. The only time they should be pointing to memory - // is when they are subslices of nonzero slices. - let (alloc, offset, n, ty) = match value.ty.kind { - ty::Array(t, n) => { - match value.val { - ConstValue::ByRef { offset, alloc, .. } => ( - alloc, - offset, - n.eval_usize(cx.tcx, cx.param_env), - t, - ), - _ => span_bug!( - pat.span, - "array pattern is {:?}", value, - ), - } - }, - ty::Slice(t) => { - match value.val { - ConstValue::Slice { data, start, end } => ( - data, - Size::from_bytes(start as u64), - (end - start) as u64, - t, - ), - ConstValue::ByRef { .. } => { - // FIXME(oli-obk): implement `deref` for `ConstValue` - return None; + PatKind::Constant { value } => { + match *constructor { + Slice(..) => { + // we extract an `Option` for the pointer because slices of zero elements don't + // necessarily point to memory, they are usually just integers. The only time + // they should be pointing to memory is when they are subslices of nonzero + // slices + let (alloc, offset, n, ty) = match value.ty.kind { + ty::Array(t, n) => { + match value.val { + ConstValue::ByRef { offset, alloc, .. } => ( + alloc, + offset, + n.eval_usize(cx.tcx, cx.param_env), + t, + ), + _ => span_bug!( + pat.span, + "array pattern is {:?}", value, + ), + } + }, + ty::Slice(t) => { + match value.val { + ConstValue::Slice { data, start, end } => ( + data, + Size::from_bytes(start as u64), + (end - start) as u64, + t, + ), + ConstValue::ByRef { .. } => { + // FIXME(oli-obk): implement `deref` for `ConstValue` + return None; + }, + _ => span_bug!( + pat.span, + "slice pattern constant must be scalar pair but is {:?}", + value, + ), + } }, _ => span_bug!( pat.span, - "slice pattern constant must be scalar pair but is {:?}", + "unexpected const-val {:?} with ctor {:?}", value, + constructor, ), - } - }, - _ => span_bug!( - pat.span, - "unexpected const-val {:?} with ctor {:?}", - value, - constructor, - ), - }; - if wild_patterns.len() as u64 == n { - // convert a constant slice/array pattern to a list of patterns. - let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?; - let ptr = Pointer::new(AllocId(0), offset); - (0..n).map(|i| { - let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?; - let scalar = alloc.read_scalar( - &cx.tcx, ptr, layout.size, - ).ok()?; - let scalar = scalar.not_undef().ok()?; - let value = ty::Const::from_scalar(cx.tcx, scalar, ty); - let pattern = Pat { - ty, - span: pat.span, - kind: box PatKind::Constant { value }, }; - Some(&*cx.pattern_arena.alloc(pattern)) - }).collect() - } else { - None + if wild_patterns.len() as u64 == n { + // convert a constant slice/array pattern to a list of patterns. + let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?; + let ptr = Pointer::new(AllocId(0), offset); + (0..n).map(|i| { + let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?; + let scalar = alloc.read_scalar( + &cx.tcx, ptr, layout.size, + ).ok()?; + let scalar = scalar.not_undef().ok()?; + let value = ty::Const::from_scalar(cx.tcx, scalar, ty); + let pattern = Pat { + ty, + span: pat.span, + kind: box PatKind::Constant { value }, + }; + Some(&*cx.pattern_arena.alloc(pattern)) + }).collect() + } else { + None + } + } + _ => { + // If the constructor is a: + // Single value: add a row if the constructor equals the pattern. + // Range: add a row if the constructor contains the pattern. + constructor_intersects_pattern(cx.tcx, cx.param_env, constructor, pat) + } } } - PatKind::Constant { .. } | PatKind::Range { .. } => { // If the constructor is a: - // - Single value: add a row if the pattern contains the constructor. - // - Range: add a row if the constructor intersects the pattern. - if should_treat_range_exhaustively(cx.tcx, constructor) { - match (IntRange::from_ctor(cx.tcx, cx.param_env, constructor), - IntRange::from_pat(cx.tcx, cx.param_env, pat)) { - (Some(ctor), Some(pat)) => { - ctor.intersection(&pat).map(|_| { - let (pat_lo, pat_hi) = pat.range.into_inner(); - let (ctor_lo, ctor_hi) = ctor.range.into_inner(); - assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi); - smallvec![] - }) - } - _ => None, - } - } else { - // Fallback for non-ranges and ranges that involve - // floating-point numbers, which are not conveniently handled - // by `IntRange`. For these cases, the constructor may not be a - // range so intersection actually devolves into being covered - // by the pattern. - match constructor_covered_by_range(cx.tcx, cx.param_env, constructor, pat) { - Ok(true) => Some(smallvec![]), - Ok(false) | Err(ErrorReported) => None, - } - } + // Single value: add a row if the pattern contains the constructor. + // Range: add a row if the constructor intersects the pattern. + constructor_intersects_pattern(cx.tcx, cx.param_env, constructor, pat) } PatKind::Array { ref prefix, ref slice, ref suffix } | @@ -2039,7 +1872,7 @@ fn specialize<'p, 'a: 'p, 'tcx>( None } } - ConstantValue(cv, _) => { + ConstantValue(cv) => { match slice_pat_covered_by_const( cx.tcx, pat.span, cv, prefix, slice, suffix, cx.param_env, ) { diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 77f3768172fb4..c521b7352214b 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -10,7 +10,6 @@ use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::lint; use rustc_errors::{Applicability, DiagnosticBuilder}; -use rustc::hir::HirId; use rustc::hir::def::*; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; @@ -63,13 +62,12 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { fn visit_local(&mut self, loc: &'tcx hir::Local) { intravisit::walk_local(self, loc); - let (msg, sp) = match loc.source { - hir::LocalSource::Normal => ("local binding", Some(loc.span)), - hir::LocalSource::ForLoopDesugar => ("`for` loop binding", None), - hir::LocalSource::AsyncFn => ("async fn binding", None), - hir::LocalSource::AwaitDesugar => ("`await` future binding", None), - }; - self.check_irrefutable(&loc.pat, msg, sp); + self.check_irrefutable(&loc.pat, match loc.source { + hir::LocalSource::Normal => "local binding", + hir::LocalSource::ForLoopDesugar => "`for` loop binding", + hir::LocalSource::AsyncFn => "async fn binding", + hir::LocalSource::AwaitDesugar => "`await` future binding", + }); // Check legality of move bindings and `@` patterns. self.check_patterns(false, &loc.pat); @@ -79,7 +77,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { intravisit::walk_body(self, body); for param in &body.params { - self.check_irrefutable(¶m.pat, "function argument", None); + self.check_irrefutable(¶m.pat, "function argument"); self.check_patterns(false, ¶m.pat); } } @@ -154,8 +152,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { self.tables ); patcx.include_lint_checks(); - let pattern = - cx.pattern_arena.alloc(expand_pattern(cx, patcx.lower_pattern(&pat))) as &_; + let pattern = expand_pattern(cx, patcx.lower_pattern(&pat)); if !patcx.errors.is_empty() { patcx.report_inlining_errors(pat.span); have_errors = true; @@ -241,11 +238,11 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { .map(|pat| smallvec![pat.0]) .collect(); let scrut_ty = self.tables.node_type(scrut.hir_id); - check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id); + check_exhaustive(cx, scrut_ty, scrut.span, &matrix); }) } - fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str, sp: Option) { + fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) { let module = self.tcx.hir().get_module_parent(pat.hir_id); MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| { let mut patcx = PatCtxt::new(self.tcx, @@ -254,12 +251,11 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { patcx.include_lint_checks(); let pattern = patcx.lower_pattern(pat); let pattern_ty = pattern.ty; - let pattern = expand_pattern(cx, pattern); let pats: Matrix<'_, '_> = vec![smallvec![ - &pattern + expand_pattern(cx, pattern) ]].into_iter().collect(); - let witnesses = match check_not_useful(cx, pattern_ty, &pats, pat.hir_id) { + let witnesses = match check_not_useful(cx, pattern_ty, &pats) { Ok(_) => return, Err(err) => err, }; @@ -270,35 +266,18 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { "refutable pattern in {}: {} not covered", origin, joined_patterns ); - let suggest_if_let = match &pat.kind { + match &pat.kind { hir::PatKind::Path(hir::QPath::Resolved(None, path)) if path.segments.len() == 1 && path.segments[0].args.is_none() => { const_not_var(&mut err, cx.tcx, pat, path); - false } _ => { err.span_label( pat.span, pattern_not_covered_label(&witnesses, &joined_patterns), ); - true - } - }; - - if let (Some(span), true) = (sp, suggest_if_let) { - err.note("`let` bindings require an \"irrefutable pattern\", like a `struct` or \ - an `enum` with only one variant"); - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - err.span_suggestion( - span, - "you might want to use `if let` to ignore the variant that isn't matched", - format!("if {} {{ /* */ }}", &snippet[..snippet.len() - 1]), - Applicability::HasPlaceholders, - ); } - err.note("for more information, visit \ - https://doc.rust-lang.org/book/ch18-02-refutability.html"); } adt_defined_here(cx, &mut err, pattern_ty, &witnesses); @@ -392,7 +371,7 @@ fn check_arms<'tcx>( for &(pat, hir_pat) in pats { let v = smallvec![pat]; - match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id) { + match is_useful(cx, &seen, &v, LeaveOutWitness) { NotUseful => { match source { hir::MatchSource::IfDesugar { .. } | @@ -468,10 +447,9 @@ fn check_not_useful( cx: &mut MatchCheckCtxt<'_, 'tcx>, ty: Ty<'tcx>, matrix: &Matrix<'_, 'tcx>, - hir_id: HirId, ) -> Result<(), Vec>> { let wild_pattern = super::Pat { ty, span: DUMMY_SP, kind: box PatKind::Wild }; - match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness, hir_id) { + 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] @@ -487,9 +465,8 @@ fn check_exhaustive<'tcx>( scrut_ty: Ty<'tcx>, sp: Span, matrix: &Matrix<'_, 'tcx>, - hir_id: HirId, ) { - let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) { + let witnesses = match check_not_useful(cx, scrut_ty, matrix) { Ok(_) => return, Err(err) => err, }; diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 98e286e61e942..4d2fee3d160ed 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -13,18 +13,19 @@ use crate::hair::constant::*; use rustc::lint; use rustc::mir::{Field, BorrowKind, Mutability}; use rustc::mir::{UserTypeProjection}; -use rustc::mir::interpret::{GlobalId, ConstValue, get_slice_bytes, sign_extend}; +use rustc::mir::interpret::{GlobalId, ConstValue, sign_extend, AllocId, Pointer}; use rustc::traits::{ObligationCause, PredicateObligation}; use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree}; use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations}; use rustc::ty::subst::{SubstsRef, GenericArg}; -use rustc::ty::layout::VariantIdx; +use rustc::ty::layout::{VariantIdx, Size}; use rustc::hir::{self, RangeEnd}; use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc::hir::ptr::P; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::fx::FxHashSet; use std::cmp::Ordering; use std::fmt; @@ -311,7 +312,10 @@ impl<'tcx> fmt::Display for Pat<'tcx> { } PatKind::Range(PatRange { lo, hi, end }) => { write!(f, "{}", lo)?; - write!(f, "{}", end)?; + match end { + RangeEnd::Included => write!(f, "..=")?, + RangeEnd::Excluded => write!(f, "..")?, + } write!(f, "{}", hi) } PatKind::Slice { ref prefix, ref slice, ref suffix } | @@ -999,21 +1003,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if self.include_lint_checks && !saw_error { // If we were able to successfully convert the const to some pat, double-check // that the type of the const obeys `#[structural_match]` constraint. - if let Some(non_sm_ty) = ty::search_for_structural_match_violation(self.tcx, cv.ty) { - let msg = match non_sm_ty { - ty::NonStructuralMatchTy::Adt(adt_def) => { - let path = self.tcx.def_path_str(adt_def.did); - format!( - "to use a constant of type `{}` in a pattern, \ - `{}` must be annotated with `#[derive(PartialEq, Eq)]`", - path, - path, - ) - } - ty::NonStructuralMatchTy::Param => { - bug!("use of constant whose type is a parameter inside a pattern"); - } - }; + if let Some(adt_def) = search_for_adt_without_structural_match(self.tcx, cv.ty) { + + let path = self.tcx.def_path_str(adt_def.did); + let msg = format!( + "to use a constant of type `{}` in a pattern, \ + `{}` must be annotated with `#[derive(PartialEq, Eq)]`", + path, + path, + ); // before issuing lint, double-check there even *is* a // semantic PartialEq for us to dispatch to. @@ -1174,6 +1172,127 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } } +/// This method traverses the structure of `ty`, trying to find an +/// instance of an ADT (i.e. struct or enum) that was declared without +/// the `#[structural_match]` attribute. +/// +/// The "structure of a type" includes all components that would be +/// considered when doing a pattern match on a constant of that +/// type. +/// +/// * This means this method descends into fields of structs/enums, +/// and also descends into the inner type `T` of `&T` and `&mut T` +/// +/// * The traversal doesn't dereference unsafe pointers (`*const T`, +/// `*mut T`), and it does not visit the type arguments of an +/// instantiated generic like `PhantomData`. +/// +/// The reason we do this search is Rust currently require all ADT's +/// reachable from a constant's type to be annotated with +/// `#[structural_match]`, an attribute which essentially says that +/// the implementation of `PartialEq::eq` behaves *equivalently* to a +/// comparison against the unfolded structure. +/// +/// For more background on why Rust has this requirement, and issues +/// that arose when the requirement was not enforced completely, see +/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307. +fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>) + -> Option<&'tcx AdtDef> +{ + // Import here (not mod level), because `TypeFoldable::fold_with` + // conflicts with `PatternFoldable::fold_with` + use crate::rustc::ty::fold::TypeVisitor; + use crate::rustc::ty::TypeFoldable; + + let mut search = Search { tcx, found: None, seen: FxHashSet::default() }; + ty.visit_with(&mut search); + return search.found; + + struct Search<'tcx> { + tcx: TyCtxt<'tcx>, + + // records the first ADT we find without `#[structural_match` + found: Option<&'tcx AdtDef>, + + // tracks ADT's previously encountered during search, so that + // we will not recur on them again. + seen: FxHashSet<&'tcx AdtDef>, + } + + impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + debug!("Search visiting ty: {:?}", ty); + + let (adt_def, substs) = match ty.kind { + ty::Adt(adt_def, substs) => (adt_def, substs), + ty::RawPtr(..) => { + // `#[structural_match]` ignores substructure of + // `*const _`/`*mut _`, so skip super_visit_with + // + // (But still tell caller to continue search.) + return false; + } + ty::FnDef(..) | ty::FnPtr(..) => { + // types of formals and return in `fn(_) -> _` are also irrelevant + // + // (But still tell caller to continue search.) + return false; + } + ty::Array(_, n) if n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) + => { + // rust-lang/rust#62336: ignore type of contents + // for empty array. + return false; + } + _ => { + ty.super_visit_with(self); + return false; + } + }; + + if !self.tcx.has_attr(adt_def.did, sym::structural_match) { + self.found = Some(&adt_def); + debug!("Search found adt_def: {:?}", adt_def); + return true // Halt visiting! + } + + if self.seen.contains(adt_def) { + debug!("Search already seen adt_def: {:?}", adt_def); + // let caller continue its search + return false; + } + + self.seen.insert(adt_def); + + // `#[structural_match]` does not care about the + // instantiation of the generics in an ADT (it + // instead looks directly at its fields outside + // this match), so we skip super_visit_with. + // + // (Must not recur on substs for `PhantomData` cf + // rust-lang/rust#55028 and rust-lang/rust#55837; but also + // want to skip substs when only uses of generic are + // behind unsafe pointers `*const T`/`*mut T`.) + + // even though we skip super_visit_with, we must recur on + // fields of ADT. + let tcx = self.tcx; + for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) { + if field_ty.visit_with(self) { + // found an ADT without `#[structural_match]`; halt visiting! + assert!(self.found.is_some()); + return true; + } + } + + // Even though we do not want to recur on substs, we do + // want our caller to continue its own search. + false + } + } +} + impl UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx @@ -1407,10 +1526,27 @@ pub fn compare_const_vals<'tcx>( if let ty::Str = ty.kind { match (a.val, b.val) { - (ConstValue::Slice { .. }, ConstValue::Slice { .. }) => { - let a_bytes = get_slice_bytes(&tcx, a.val); - let b_bytes = get_slice_bytes(&tcx, b.val); - return from_bool(a_bytes == b_bytes); + ( + ConstValue::Slice { data: alloc_a, start: offset_a, end: end_a }, + ConstValue::Slice { data: alloc_b, start: offset_b, end: end_b }, + ) => { + let len_a = end_a - offset_a; + let len_b = end_b - offset_b; + let a = alloc_a.get_bytes( + &tcx, + // invent a pointer, only the offset is relevant anyway + Pointer::new(AllocId(0), Size::from_bytes(offset_a as u64)), + Size::from_bytes(len_a as u64), + ); + let b = alloc_b.get_bytes( + &tcx, + // invent a pointer, only the offset is relevant anyway + Pointer::new(AllocId(0), Size::from_bytes(offset_b as u64)), + Size::from_bytes(len_b as u64), + ); + if let (Ok(a), Ok(b)) = (a, b) { + return from_bool(a == b); + } } _ => (), } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 9ab347957f97a..d120412c901a6 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -44,14 +44,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { 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_for_fn_ptr( - *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)?; } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index d929e958f05d0..fdf85260c3d96 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -12,7 +12,7 @@ use rustc::ty::layout::{ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::query::TyCtxtAt; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc::mir::interpret::{ GlobalId, Scalar, Pointer, FrameInfo, AllocId, InterpResult, truncate, sign_extend, @@ -35,7 +35,7 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> { pub(crate) param_env: ty::ParamEnv<'tcx>, /// The virtual memory system. - pub memory: Memory<'mir, 'tcx, M>, + pub(crate) memory: Memory<'mir, 'tcx, M>, /// The virtual call stack. pub(crate) stack: Vec>, @@ -91,7 +91,7 @@ pub struct Frame<'mir, 'tcx, Tag=(), Extra=()> { pub extra: Extra, } -#[derive(Clone, Eq, PartialEq, Debug)] // Miri debug-prints these +#[derive(Clone, Debug, Eq, PartialEq, Hash)] pub enum StackPopCleanup { /// Jump to the next block in the caller, or cause UB if None (that's a function /// that may never return). Also store layout of return place so @@ -113,7 +113,7 @@ pub struct LocalState<'tcx, Tag=(), Id=AllocId> { } /// Current value of a local variable -#[derive(Clone, PartialEq, Eq, Debug)] // Miri debug-prints these +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum LocalValue { /// This local is not currently alive, and cannot be used at all. Dead, @@ -211,6 +211,16 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } + #[inline(always)] + pub fn memory(&self) -> &Memory<'mir, 'tcx, M> { + &self.memory + } + + #[inline(always)] + pub fn memory_mut(&mut self) -> &mut Memory<'mir, 'tcx, M> { + &mut self.memory + } + #[inline(always)] pub fn force_ptr( &self, diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 646d1783c8ec9..ec06b6298e112 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -73,7 +73,8 @@ fn intern_shallow<'rt, 'mir, 'tcx>( ); // remove allocation let tcx = ecx.tcx; - let (kind, mut alloc) = match ecx.memory.alloc_map.remove(&alloc_id) { + 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 @@ -331,7 +332,7 @@ pub fn intern_const_alloc_recursive( let mut todo: Vec<_> = leftover_allocations.iter().cloned().collect(); while let Some(alloc_id) = todo.pop() { - if let Some((_, mut alloc)) = ecx.memory.alloc_map.remove(&alloc_id) { + 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. @@ -349,7 +350,7 @@ pub fn intern_const_alloc_recursive( todo.push(reloc); } } - } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) { + } else if ecx.memory().dead_alloc_map.contains_key(&alloc_id) { // dangling pointer throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into())) } diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs index f1f9fac08ca3a..a8b4d65e7d4b0 100644 --- a/src/librustc_mir/interpret/intrinsics/type_name.rs +++ b/src/librustc_mir/interpret/intrinsics/type_name.rs @@ -67,8 +67,9 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::Opaque(def_id, substs) | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) - | ty::Closure(def_id, substs) - | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs), + | ty::Closure(def_id, ty::ClosureSubsts { substs }) + | ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) + => self.print_def_path(def_id, substs), ty::Foreign(def_id) => self.print_def_path(def_id, &[]), ty::GeneratorWitness(_) => { @@ -148,7 +149,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { self.path.push_str("::"); - self.path.push_str(&disambiguated_data.data.as_symbol().as_str()); + self.path.push_str(&disambiguated_data.data.as_interned_str().as_str()); Ok(self) } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index d113ee33162d2..924474c53175c 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -22,7 +22,7 @@ use super::{ Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg, }; -#[derive(Debug, PartialEq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] pub enum MemoryKind { /// Error if deallocated except during a stack pop Stack, @@ -785,26 +785,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { self.get(ptr.alloc_id)?.read_c_str(self, ptr) } - /// Writes the given stream of bytes into memory. - /// - /// Performs appropriate bounds checks. - pub fn write_bytes( - &mut self, - ptr: Scalar, - src: impl IntoIterator, - ) -> InterpResult<'tcx> - { - let src = src.into_iter(); - let size = Size::from_bytes(src.size_hint().0 as u64); - // `write_bytes` checks that this lower bound matches the upper bound matches reality. - let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(1).unwrap())? { - Some(ptr) => ptr, - None => return Ok(()), // zero-sized access - }; - let tcx = self.tcx.tcx; - self.get_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src) - } - /// Expects the caller to have checked bounds and alignment. pub fn copy( &mut self, diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 4fd5e6a543551..861e5ebef877d 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -26,7 +26,7 @@ pub use rustc::mir::interpret::ScalarMaybeUndef; /// operations and fat pointers. This idea was taken from rustc's codegen. /// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely /// defined on `Immediate`, and do not have to work with a `Place`. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub enum Immediate { Scalar(ScalarMaybeUndef), ScalarPair(ScalarMaybeUndef, ScalarMaybeUndef), @@ -123,7 +123,7 @@ impl<'tcx, Tag> ::std::ops::Deref for ImmTy<'tcx, Tag> { /// An `Operand` is the result of computing a `mir::Operand`. It can be immediate, /// or still in memory. The latter is an optimization, to delay reading that chunk of /// memory and to avoid having to store arbitrary-sized data here. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub enum Operand { Immediate(Immediate), Indirect(MemPlace), @@ -153,7 +153,7 @@ impl Operand { } } -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct OpTy<'tcx, Tag=()> { op: Operand, // Keep this private, it helps enforce invariants pub layout: TyLayout<'tcx>, @@ -589,7 +589,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let ptr = self.tag_static_base_pointer(Pointer::new(id, offset)); Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi)) }, - ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x).into()), + ConstValue::Scalar(x) => + Operand::Immediate(tag_scalar(x).into()), ConstValue::Slice { data, start, end } => { // We rely on mutability being set correctly in `data` to prevent writes // where none should happen. @@ -605,7 +606,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } ConstValue::Param(..) | ConstValue::Infer(..) | - ConstValue::Bound(..) | ConstValue::Placeholder(..) | ConstValue::Unevaluated(..) => bug!("eval_const_to_op: Unexpected ConstValue {:?}", val), @@ -647,7 +647,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let bits_discr = raw_discr .not_undef() .and_then(|raw_discr| self.force_bits(raw_discr, discr_val.layout.size)) - .map_err(|_| err_ub!(InvalidDiscriminant(raw_discr.erase_tag())))?; + .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 discriminant layout @@ -664,20 +664,16 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bits_discr }; // Make sure we catch invalid discriminants - let index = match rval.layout.ty.kind { + let index = match &rval.layout.ty.kind { ty::Adt(adt, _) => adt .discriminants(self.tcx.tcx) .find(|(_, var)| var.val == real_discr), - ty::Generator(def_id, substs, _) => { - let substs = substs.as_generator(); - substs - .discriminants(def_id, self.tcx.tcx) - .find(|(_, var)| var.val == real_discr) - } + ty::Generator(def_id, substs, _) => substs + .discriminants(*def_id, self.tcx.tcx) + .find(|(_, var)| var.val == real_discr), _ => bug!("tagged layout for non-adt non-generator"), - }.ok_or_else( - || err_ub!(InvalidDiscriminant(raw_discr.erase_tag())) + || err_unsup!(InvalidDiscriminant(raw_discr.erase_tag())) )?; (real_discr, index.0) }, @@ -689,7 +685,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { 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_ub!(InvalidDiscriminant(ScalarMaybeUndef::Undef)) + err_unsup!(InvalidDiscriminant(ScalarMaybeUndef::Undef)) })?; match raw_discr.to_bits_or_ptr(discr_val.layout.size, self) { Err(ptr) => { @@ -697,7 +693,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let ptr_valid = niche_start == 0 && variants_start == variants_end && !self.memory.ptr_may_be_null(ptr); if !ptr_valid { - throw_ub!(InvalidDiscriminant(raw_discr.erase_tag().into())) + throw_unsup!(InvalidDiscriminant(raw_discr.erase_tag().into())) } (dataful_variant.as_u32() as u128, dataful_variant) }, diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 0289c52fd3744..1166ca9bf2444 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -9,7 +9,7 @@ use rustc::mir; use rustc::mir::interpret::truncate; use rustc::ty::{self, Ty}; use rustc::ty::layout::{ - self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt + self, Size, Abi, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt }; use rustc::ty::TypeFoldable; @@ -377,17 +377,20 @@ where layout::FieldPlacement::Array { stride, .. } => { let len = base.len(self)?; if field >= len { - // This can be violated because the index (field) can be a runtime value - // provided by the user. + // This can be violated because this runs during promotion on code where the + // type system has not yet ensured that such things don't happen. debug!("tried to access element {} of array/slice with length {}", field, len); throw_panic!(BoundsCheck { len, index: field }); } stride * field } layout::FieldPlacement::Union(count) => { + // FIXME(#64506) `UninhabitedValue` can be removed when this issue is resolved + if base.layout.abi == Abi::Uninhabited { + throw_unsup!(UninhabitedValue); + } assert!(field < count as u64, - "Tried to access field {} of union {:#?} with {} fields", - field, base.layout, count); + "Tried to access field {} of union with {} fields", field, count); // Offset is always 0 Size::from_bytes(0) } @@ -591,13 +594,6 @@ where 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); - - // Even after getting `substs` from the frame, this instance may still be - // polymorphic because `ConstProp` will try to promote polymorphic MIR. - if instance.needs_subst() { - throw_inval!(TooGeneric); - } - self.const_eval_raw(GlobalId { instance, promoted: Some(promoted), @@ -1031,13 +1027,9 @@ where variant_index: VariantIdx, dest: PlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { - let variant_scalar = Scalar::from_u32(variant_index.as_u32()).into(); - match dest.layout.variants { layout::Variants::Single { index } => { - if index != variant_index { - throw_ub!(InvalidDiscriminant(variant_scalar)); - } + assert_eq!(index, variant_index); } layout::Variants::Multiple { discr_kind: layout::DiscriminantKind::Tag, @@ -1045,9 +1037,7 @@ where discr_index, .. } => { - if !dest.layout.ty.variant_range(*self.tcx).unwrap().contains(&variant_index) { - throw_ub!(InvalidDiscriminant(variant_scalar)); - } + assert!(dest.layout.ty.variant_range(*self.tcx).unwrap().contains(&variant_index)); let discr_val = dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val; @@ -1070,9 +1060,9 @@ where discr_index, .. } => { - if !variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len() { - throw_ub!(InvalidDiscriminant(variant_scalar)); - } + assert!( + variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len(), + ); if variant_index != dataful_variant { let variants_start = niche_variants.start().as_u32(); let variant_index_relative = variant_index.as_u32() diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 7ce151e087a6b..2cac8bb0c517e 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -17,7 +17,7 @@ use rustc::mir::interpret::{ use rustc::ty::{self, TyCtxt}; use rustc::ty::layout::{Align, Size}; use rustc_data_structures::fx::FxHashSet; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use syntax::ast::Mutability; use syntax::source_map::Span; @@ -52,9 +52,9 @@ impl<'mir, 'tcx> InfiniteLoopDetector<'mir, 'tcx> { ) -> InterpResult<'tcx, ()> { // Compute stack's hash before copying anything let mut hcx = tcx.get_stable_hashing_context(); - let mut hasher = StableHasher::new(); + let mut hasher = StableHasher::::new(); stack.hash_stable(&mut hcx, &mut hasher); - let hash = hasher.finish::(); + let hash = hasher.finish(); // Check if we know that hash already if self.hashes.is_empty() { @@ -428,9 +428,9 @@ impl<'mir, 'tcx> Hash for InterpSnapshot<'mir, 'tcx> { fn hash(&self, state: &mut H) { // Implement in terms of hash stable, so that k1 == k2 -> hash(k1) == hash(k2) let mut hcx = self.memory.tcx.get_stable_hashing_context(); - let mut hasher = StableHasher::new(); + let mut hasher = StableHasher::::new(); self.hash_stable(&mut hcx, &mut hasher); - hasher.finish::().hash(state) + hasher.finish().hash(state) } } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 7f6baf0bb49c1..ef6b7d626e7a4 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -140,12 +140,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .read_immediate(self.eval_operand(len, None)?) .expect("can't eval len") .to_scalar()? - .to_bits(self.memory.pointer_size())? as u64; + .to_bits(self.memory().pointer_size())? as u64; let index = self .read_immediate(self.eval_operand(index, None)?) .expect("can't eval index") .to_scalar()? - .to_bits(self.memory.pointer_size())? as u64; + .to_bits(self.memory().pointer_size())? as u64; err_panic!(BoundsCheck { len, index }) } Overflow(op) => err_panic!(Overflow(*op)), @@ -263,7 +263,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } ty::InstanceDef::VtableShim(..) | - ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::DropGlue(..) | diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 3444fb60f333b..853fcb1beabf5 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -344,7 +344,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> match self.walk_value(op) { Ok(()) => Ok(()), Err(err) => match err.kind { - err_ub!(InvalidDiscriminant(val)) => + err_unsup!(InvalidDiscriminant(val)) => throw_validation_failure!( val, self.path, "a valid enum discriminant" ), diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 98d5487870a4d..938dab57181d6 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(core_intrinsics)] #![feature(const_fn)] #![feature(decl_macro)] -#![feature(drain_filter)] #![feature(exhaustive_patterns)] #![feature(never_type)] #![feature(specialization)] @@ -23,9 +22,9 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(slice_concat_ext)] #![feature(trusted_len)] #![feature(try_blocks)] +#![feature(mem_take)] #![feature(associated_type_bounds)] #![feature(range_is_empty)] -#![feature(stmt_expr_attributes)] #![recursion_limit="256"] diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir/lints.rs index 158b730b9bd43..4f978051eaccd 100644 --- a/src/librustc_mir/lints.rs +++ b/src/librustc_mir/lints.rs @@ -1,4 +1,4 @@ -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::FnKind; use rustc::hir::map::blocks::FnLikeNode; @@ -72,11 +72,13 @@ fn check_fn_for_unconditional_recursion( let caller_substs = &InternalSubsts::identity_for_item(tcx, def_id)[..trait_substs_count]; while let Some(bb) = reachable_without_self_call_queue.pop() { - if !visited.insert(bb) { + if visited.contains(bb) { //already done continue; } + visited.insert(bb); + let block = &basic_blocks[bb]; if let Some(ref terminator) = block.terminator { diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 5e31b80bec6d3..cc8f4759e1837 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -194,12 +194,12 @@ use crate::monomorphize; use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap}; use rustc::util::common::time; -use rustc_index::bit_set::GrowableBitSet; +use rustc_data_structures::bit_set::GrowableBitSet; use rustc_data_structures::sync::{MTRef, MTLock, ParallelIterator, par_iter}; use std::iter; -#[derive(PartialEq)] +#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] pub enum MonoItemCollectionMode { Eager, Lazy @@ -285,11 +285,7 @@ pub fn collect_crate_mono_items( tcx: TyCtxt<'_>, mode: MonoItemCollectionMode, ) -> (FxHashSet>, InliningMap<'_>) { - let _prof_timer = tcx.prof.generic_activity("monomorphization_collector"); - let roots = time(tcx.sess, "collecting roots", || { - let _prof_timer = tcx.prof - .generic_activity("monomorphization_collector_root_collections"); collect_roots(tcx, mode) }); @@ -299,9 +295,6 @@ pub fn collect_crate_mono_items( let mut inlining_map = MTLock::new(InliningMap::new()); { - let _prof_timer = tcx.prof - .generic_activity("monomorphization_collector_graph_walk"); - let visited: MTRef<'_, _> = &mut visited; let inlining_map: MTRef<'_, _> = &mut inlining_map; @@ -588,8 +581,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { match source_ty.kind { ty::Closure(def_id, substs) => { let instance = Instance::resolve_closure( - self.tcx, def_id, - substs, ty::ClosureKind::FnOnce); + self.tcx, def_id, substs, ty::ClosureKind::FnOnce); if should_monomorphize_locally(self.tcx, &instance) { self.output.push(create_fn_mono_item(instance)); } @@ -721,12 +713,10 @@ fn visit_fn_use<'tcx>( output: &mut Vec>, ) { if let ty::FnDef(def_id, substs) = ty.kind { - let resolver = if is_direct_call { - ty::Instance::resolve - } else { - ty::Instance::resolve_for_fn_ptr - }; - let instance = resolver(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap(); + let instance = ty::Instance::resolve(tcx, + ty::ParamEnv::reveal_all(), + def_id, + substs).unwrap(); visit_instance_use(tcx, instance, is_direct_call, output); } } @@ -749,7 +739,6 @@ fn visit_instance_use<'tcx>( } } ty::InstanceDef::VtableShim(..) | - ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::Virtual(..) | ty::InstanceDef::DropGlue(_, None) => { // don't need to emit shim if we are calling directly. @@ -776,7 +765,6 @@ fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx let def_id = match instance.def { ty::InstanceDef::Item(def_id) => def_id, ty::InstanceDef::VtableShim(..) | - ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::Virtual(..) | ty::InstanceDef::FnPtrShim(..) | @@ -1276,14 +1264,7 @@ fn collect_const<'tcx>( ) { debug!("visiting const {:?}", constant); - let param_env = ty::ParamEnv::reveal_all(); - let substituted_constant = tcx.subst_and_normalize_erasing_regions( - param_substs, - param_env, - &constant, - ); - - match substituted_constant.val { + match constant.val { ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output), ConstValue::Slice { data: alloc, start: _, end: _ } | @@ -1293,6 +1274,12 @@ fn collect_const<'tcx>( } } ConstValue::Unevaluated(def_id, substs) => { + let param_env = ty::ParamEnv::reveal_all(); + let substs = tcx.subst_and_normalize_erasing_regions( + param_substs, + param_env, + &substs, + ); let instance = ty::Instance::resolve(tcx, param_env, def_id, @@ -1309,7 +1296,7 @@ fn collect_const<'tcx>( tcx.def_span(def_id), "collection encountered polymorphic constant", ), } - }, + } _ => {}, } } diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs new file mode 100644 index 0000000000000..e63426281bf21 --- /dev/null +++ b/src/librustc_mir/monomorphize/item.rs @@ -0,0 +1,204 @@ +use rustc::hir::def_id::LOCAL_CRATE; +use rustc::mir::mono::MonoItem; +use rustc::session::config::OptLevel; +use rustc::ty::{self, TyCtxt, Instance}; +use rustc::ty::subst::InternalSubsts; +use rustc::ty::print::obsolete::DefPathBasedNames; +use syntax::attr::InlineAttr; +use std::fmt; +use rustc::mir::mono::Linkage; +use syntax_pos::symbol::InternedString; +use syntax::source_map::Span; + +/// Describes how a monomorphization will be instantiated in object files. +#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] +pub enum InstantiationMode { + /// There will be exactly one instance of the given MonoItem. It will have + /// external linkage so that it can be linked to from other codegen units. + GloballyShared { + /// In some compilation scenarios we may decide to take functions that + /// are typically `LocalCopy` and instead move them to `GloballyShared` + /// to avoid codegenning them a bunch of times. In this situation, + /// however, our local copy may conflict with other crates also + /// inlining the same function. + /// + /// This flag indicates that this situation is occurring, and informs + /// symbol name calculation that some extra mangling is needed to + /// avoid conflicts. Note that this may eventually go away entirely if + /// ThinLTO enables us to *always* have a globally shared instance of a + /// function within one crate's compilation. + may_conflict: bool, + }, + + /// Each codegen unit containing a reference to the given MonoItem will + /// have its own private copy of the function (with internal linkage). + LocalCopy, +} + +pub trait MonoItemExt<'tcx>: fmt::Debug { + fn as_mono_item(&self) -> &MonoItem<'tcx>; + + fn is_generic_fn(&self) -> bool { + match *self.as_mono_item() { + MonoItem::Fn(ref instance) => { + instance.substs.non_erasable_generics().next().is_some() + } + MonoItem::Static(..) | + MonoItem::GlobalAsm(..) => false, + } + } + + fn symbol_name(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName { + match *self.as_mono_item() { + MonoItem::Fn(instance) => tcx.symbol_name(instance), + MonoItem::Static(def_id) => { + tcx.symbol_name(Instance::mono(tcx, def_id)) + } + MonoItem::GlobalAsm(hir_id) => { + let def_id = tcx.hir().local_def_id(hir_id); + ty::SymbolName { + name: InternedString::intern(&format!("global_asm_{:?}", def_id)) + } + } + } + } + fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode { + let inline_in_all_cgus = + tcx.sess.opts.debugging_opts.inline_in_all_cgus.unwrap_or_else(|| { + tcx.sess.opts.optimize != OptLevel::No + }) && !tcx.sess.opts.cg.link_dead_code; + + match *self.as_mono_item() { + MonoItem::Fn(ref instance) => { + let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id); + // If this function isn't inlined or otherwise has explicit + // linkage, then we'll be creating a globally shared version. + if self.explicit_linkage(tcx).is_some() || + !instance.def.requires_local(tcx) || + Some(instance.def_id()) == entry_def_id + { + return InstantiationMode::GloballyShared { may_conflict: false } + } + + // At this point we don't have explicit linkage and we're an + // inlined function. If we're inlining into all CGUs then we'll + // be creating a local copy per CGU + if inline_in_all_cgus { + return InstantiationMode::LocalCopy + } + + // Finally, if this is `#[inline(always)]` we're sure to respect + // that with an inline copy per CGU, but otherwise we'll be + // creating one copy of this `#[inline]` function which may + // conflict with upstream crates as it could be an exported + // symbol. + match tcx.codegen_fn_attrs(instance.def_id()).inline { + InlineAttr::Always => InstantiationMode::LocalCopy, + _ => { + InstantiationMode::GloballyShared { may_conflict: true } + } + } + } + MonoItem::Static(..) | + MonoItem::GlobalAsm(..) => { + InstantiationMode::GloballyShared { may_conflict: false } + } + } + } + + fn explicit_linkage(&self, tcx: TyCtxt<'tcx>) -> Option { + let def_id = match *self.as_mono_item() { + MonoItem::Fn(ref instance) => instance.def_id(), + MonoItem::Static(def_id) => def_id, + MonoItem::GlobalAsm(..) => return None, + }; + + let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id); + codegen_fn_attrs.linkage + } + + /// Returns `true` if this instance is instantiable - whether it has no unsatisfied + /// predicates. + /// + /// In order to codegen an item, all of its predicates must hold, because + /// otherwise the item does not make sense. Type-checking ensures that + /// the predicates of every item that is *used by* a valid item *do* + /// hold, so we can rely on that. + /// + /// However, we codegen collector roots (reachable items) and functions + /// in vtables when they are seen, even if they are not used, and so they + /// might not be instantiable. For example, a programmer can define this + /// public function: + /// + /// pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { + /// <&mut () as Clone>::clone(&s); + /// } + /// + /// That function can't be codegened, because the method `<&mut () as Clone>::clone` + /// does not exist. Luckily for us, that function can't ever be used, + /// because that would require for `&'a mut (): Clone` to hold, so we + /// can just not emit any code, or even a linker reference for it. + /// + /// Similarly, if a vtable method has such a signature, and therefore can't + /// be used, we can just not emit it and have a placeholder (a null pointer, + /// which will never be accessed) in its place. + fn is_instantiable(&self, tcx: TyCtxt<'tcx>) -> bool { + debug!("is_instantiable({:?})", self); + let (def_id, substs) = match *self.as_mono_item() { + MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs), + MonoItem::Static(def_id) => (def_id, InternalSubsts::empty()), + // global asm never has predicates + MonoItem::GlobalAsm(..) => return true + }; + + tcx.substitute_normalize_and_test_predicates((def_id, &substs)) + } + + fn to_string(&self, tcx: TyCtxt<'tcx>, debug: bool) -> String { + return match *self.as_mono_item() { + MonoItem::Fn(instance) => { + to_string_internal(tcx, "fn ", instance, debug) + }, + MonoItem::Static(def_id) => { + let instance = Instance::new(def_id, tcx.intern_substs(&[])); + to_string_internal(tcx, "static ", instance, debug) + }, + MonoItem::GlobalAsm(..) => { + "global_asm".to_string() + } + }; + + fn to_string_internal<'a, 'tcx>( + tcx: TyCtxt<'tcx>, + prefix: &str, + instance: Instance<'tcx>, + debug: bool, + ) -> String { + let mut result = String::with_capacity(32); + result.push_str(prefix); + let printer = DefPathBasedNames::new(tcx, false, false); + printer.push_instance_as_string(instance, &mut result, debug); + result + } + } + + fn local_span(&self, tcx: TyCtxt<'tcx>) -> Option { + match *self.as_mono_item() { + MonoItem::Fn(Instance { def, .. }) => { + tcx.hir().as_local_hir_id(def.def_id()) + } + MonoItem::Static(def_id) => { + tcx.hir().as_local_hir_id(def_id) + } + MonoItem::GlobalAsm(hir_id) => { + Some(hir_id) + } + }.map(|hir_id| tcx.hir().span(hir_id)) + } +} + +impl MonoItemExt<'tcx> for MonoItem<'tcx> { + fn as_mono_item(&self) -> &MonoItem<'tcx> { + self + } +} diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 42f08771f866d..c193911247e2b 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -96,7 +96,7 @@ use std::collections::hash_map::Entry; use std::cmp; use std::sync::Arc; -use syntax::symbol::Symbol; +use syntax::symbol::InternedString; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def::DefKind; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; @@ -121,7 +121,7 @@ pub enum PartitioningStrategy { } // Anything we can't find a proper codegen unit for goes into this. -fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> Symbol { +fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> InternedString { name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu")) } @@ -134,15 +134,10 @@ pub fn partition<'tcx, I>( where I: Iterator>, { - let _prof_timer = tcx.prof.generic_activity("cgu_partitioning"); - // In the first step, we place all regular monomorphizations into their // respective 'home' codegen unit. Regular monomorphizations are all // functions and statics defined in the local crate. - let mut initial_partitioning = { - let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots"); - place_root_mono_items(tcx, mono_items) - }; + let mut initial_partitioning = place_root_mono_items(tcx, mono_items); initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx)); @@ -151,8 +146,8 @@ where // If the partitioning should produce a fixed count of codegen units, merge // until that count is reached. if let PartitioningStrategy::FixedUnitCount(count) = strategy { - let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus"); merge_codegen_units(tcx, &mut initial_partitioning, count); + debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter()); } @@ -160,11 +155,8 @@ where // monomorphizations have to go into each codegen unit. These additional // monomorphizations can be drop-glue, functions from external crates, and // local functions the definition of which is marked with `#[inline]`. - let mut post_inlining = { - let _prof_timer = - tcx.prof.generic_activity("cgu_partitioning_place_inline_items"); - place_inlined_mono_items(initial_partitioning, inlining_map) - }; + let mut post_inlining = place_inlined_mono_items(initial_partitioning, + inlining_map); post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx)); @@ -173,8 +165,6 @@ where // Next we try to make as many symbols "internal" as possible, so LLVM has // more freedom to optimize. if !tcx.sess.opts.cg.link_dead_code { - let _prof_timer = - tcx.prof.generic_activity("cgu_partitioning_internalize_symbols"); internalize_symbols(tcx, &mut post_inlining, inlining_map); } @@ -185,7 +175,9 @@ where internalization_candidates: _, } = post_inlining; - result.sort_by_cached_key(|cgu| cgu.name().as_str()); + result.sort_by(|cgu1, cgu2| { + cgu1.name().cmp(cgu2.name()) + }); result } @@ -201,7 +193,7 @@ struct PreInliningPartitioning<'tcx> { /// to keep track of that. #[derive(Clone, PartialEq, Eq, Debug)] enum MonoItemPlacement { - SingleCgu { cgu_name: Symbol }, + SingleCgu { cgu_name: InternedString }, MultipleCgus, } @@ -249,8 +241,8 @@ where None => fallback_cgu_name(cgu_name_builder), }; - let codegen_unit = codegen_units.entry(codegen_unit_name) - .or_insert_with(|| CodegenUnit::new(codegen_unit_name)); + let codegen_unit = codegen_units.entry(codegen_unit_name.clone()) + .or_insert_with(|| CodegenUnit::new(codegen_unit_name.clone())); let mut can_be_internalized = true; let (linkage, visibility) = mono_item_linkage_and_visibility( @@ -271,7 +263,8 @@ where // crate with just types (for example), we could wind up with no CGU. if codegen_units.is_empty() { let codegen_unit_name = fallback_cgu_name(cgu_name_builder); - codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name)); + codegen_units.insert(codegen_unit_name.clone(), + CodegenUnit::new(codegen_unit_name.clone())); } PreInliningPartitioning { @@ -336,7 +329,6 @@ fn mono_item_visibility( // These are all compiler glue and such, never exported, always hidden. InstanceDef::VtableShim(..) | - InstanceDef::ReifyShim(..) | InstanceDef::FnPtrShim(..) | InstanceDef::Virtual(..) | InstanceDef::Intrinsic(..) | @@ -489,7 +481,7 @@ fn merge_codegen_units<'tcx>( // smallest into each other) we're sure to start off with a deterministic // order (sorted by name). This'll mean that if two cgus have the same size // the stable sort below will keep everything nice and deterministic. - codegen_units.sort_by_cached_key(|cgu| cgu.name().as_str()); + codegen_units.sort_by_key(|cgu| *cgu.name()); // Merge the two smallest codegen units until the target size is reached. while codegen_units.len() > target_cgu_count { @@ -502,9 +494,6 @@ fn merge_codegen_units<'tcx>( for (k, v) in smallest.items_mut().drain() { second_smallest.items_mut().insert(k, v); } - debug!("CodegenUnit {} merged in to CodegenUnit {}", - smallest.name(), - second_smallest.name()); } let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); @@ -534,7 +523,7 @@ fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning< follow_inlining(*root, inlining_map, &mut reachable); } - let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name()); + let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name().clone()); // Add all monomorphizations that are not already there. for mono_item in reachable { @@ -561,8 +550,8 @@ fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning< Entry::Occupied(e) => { let placement = e.into_mut(); debug_assert!(match *placement { - MonoItemPlacement::SingleCgu { cgu_name } => { - cgu_name != new_codegen_unit.name() + MonoItemPlacement::SingleCgu { ref cgu_name } => { + *cgu_name != *new_codegen_unit.name() } MonoItemPlacement::MultipleCgus => true, }); @@ -570,7 +559,7 @@ fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning< } Entry::Vacant(e) => { e.insert(MonoItemPlacement::SingleCgu { - cgu_name: new_codegen_unit.name() + cgu_name: new_codegen_unit.name().clone() }); } } @@ -635,7 +624,7 @@ fn internalize_symbols<'tcx>( // accessed from outside its defining codegen unit. for cgu in &mut partitioning.codegen_units { let home_cgu = MonoItemPlacement::SingleCgu { - cgu_name: cgu.name() + cgu_name: cgu.name().clone() }; for (accessee, linkage_and_visibility) in cgu.items_mut() { @@ -675,7 +664,6 @@ fn characteristic_def_id_of_mono_item<'tcx>( let def_id = match instance.def { ty::InstanceDef::Item(def_id) => def_id, ty::InstanceDef::VtableShim(..) | - ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::Intrinsic(..) | @@ -714,7 +702,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( } } -type CguNameCache = FxHashMap<(DefId, bool), Symbol>; +type CguNameCache = FxHashMap<(DefId, bool), InternedString>; fn compute_codegen_unit_name( tcx: TyCtxt<'_>, @@ -722,7 +710,7 @@ fn compute_codegen_unit_name( def_id: DefId, volatile: bool, cache: &mut CguNameCache, -) -> Symbol { +) -> InternedString { // Find the innermost module that is not nested within a function. let mut current_def_id = def_id; let mut cgu_def_id = None; @@ -759,7 +747,7 @@ fn compute_codegen_unit_name( let components = def_path .data .iter() - .map(|part| part.data.as_symbol()); + .map(|part| part.data.as_interned_str()); let volatile_suffix = if volatile { Some("volatile") @@ -774,7 +762,7 @@ fn compute_codegen_unit_name( fn numbered_codegen_unit_name( name_builder: &mut CodegenUnitNameBuilder<'_>, index: usize, -) -> Symbol { +) -> InternedString { name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index)) } @@ -786,7 +774,7 @@ where if cfg!(debug_assertions) { debug!("{}", label); for cgu in cgus { - debug!("CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate()); + debug!("CodegenUnit {}:", cgu.name()); for (mono_item, linkage) in cgu.items() { let symbol_name = mono_item.symbol_name(tcx).name.as_str(); @@ -794,11 +782,10 @@ where let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..]) .unwrap_or(""); - debug!(" - {} [{:?}] [{}] estimated size {}", + debug!(" - {} [{:?}] [{}]", mono_item.to_string(tcx, true), linkage, - symbol_hash, - mono_item.size_estimate(tcx)); + symbol_hash); } debug!(""); @@ -926,7 +913,7 @@ fn collect_and_partition_mono_items( for (&mono_item, &linkage) in cgu.items() { item_to_cgus.entry(mono_item) .or_default() - .push((cgu.name(), linkage)); + .push((cgu.name().clone(), linkage)); } } @@ -988,7 +975,7 @@ pub fn provide(providers: &mut Providers<'_>) { providers.codegen_unit = |tcx, name| { let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); all.iter() - .find(|cgu| cgu.name() == name) + .find(|cgu| *cgu.name() == name) .cloned() .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name)) }; diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 177639956f717..4fae0976ffb5a 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -6,7 +6,7 @@ use rustc::ty::layout::VariantIdx; use rustc::ty::subst::{Subst, InternalSubsts}; use rustc::ty::query::Providers; -use rustc_index::vec::{IndexVec, Idx}; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_target::spec::abi::Abi; use syntax_pos::{Span, sym}; @@ -66,12 +66,9 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx Some(arg_tys) ) } - // We are generating a call back to our def-id, which the - // codegen backend knows to turn to an actual virtual call. - ty::InstanceDef::Virtual(def_id, _) | - // ...or we are generating a direct call to a function for which indirect calls must be - // codegen'd differently than direct ones (example: #[track_caller]) - ty::InstanceDef::ReifyShim(def_id) => { + ty::InstanceDef::Virtual(def_id, _) => { + // We are generating a call back to our def-id, which the + // codegen backend knows to turn to an actual virtual call. build_call_shim( tcx, def_id, @@ -117,7 +114,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx run_passes(tcx, &mut result, instance, None, MirPhase::Const, &[ &add_moves_for_packed_drops::AddMovesForPackedDrops, - &no_landing_pads::NoLandingPads::new(tcx), + &no_landing_pads::NoLandingPads, &remove_noop_landing_pads::RemoveNoopLandingPads, &simplify::SimplifyCfg::new("make_shim"), &add_call_guards::CriticalCallEdges, @@ -172,7 +169,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) // Check if this is a generator, if so, return the drop glue for it if let Some(&ty::TyS { kind: ty::Generator(gen_def_id, substs, _), .. }) = ty { let body = &**tcx.optimized_mir(gen_def_id).generator_drop.as_ref().unwrap(); - return body.subst(tcx, substs); + return body.subst(tcx, substs.substs); } let substs = if let Some(ty) = ty { @@ -231,7 +228,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) tcx, param_env }; - let dropee = tcx.mk_place_deref(dropee_ptr); + let dropee = dropee_ptr.deref(); let resume_block = elaborator.patch.resume_block(); elaborate_drops::elaborate_drop( &mut elaborator, @@ -312,7 +309,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env, builder.span); let dest = Place::return_place(); - let src = tcx.mk_place_deref(Place::from(Local::new(1+0))); + let src = Place::from(Local::new(1+0)).deref(); match self_ty.kind { _ if is_copy => builder.copy_shim(), @@ -323,7 +320,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - ty::Closure(def_id, substs) => { builder.tuple_like_shim( dest, src, - substs.as_closure().upvar_tys(def_id, tcx) + substs.upvar_tys(def_id, tcx) ) } ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()), @@ -415,7 +412,7 @@ impl CloneShimBuilder<'tcx> { } fn copy_shim(&mut self) { - let rcvr = self.tcx.mk_place_deref(Place::from(Local::new(1+0))); + let rcvr = Place::from(Local::new(1+0)).deref(); let ret_statement = self.make_statement( StatementKind::Assign( box( @@ -561,8 +558,8 @@ impl CloneShimBuilder<'tcx> { // BB #2 // `dest[i] = Clone::clone(src[beg])`; // Goto #3 if ok, #5 if unwinding happens. - let dest_field = self.tcx.mk_place_index(dest.clone(), beg); - let src_field = self.tcx.mk_place_index(src, beg); + let dest_field = dest.clone().index(beg); + let src_field = src.index(beg); self.make_clone_call(dest_field, src_field, ty, BasicBlock::new(3), BasicBlock::new(5)); @@ -616,7 +613,7 @@ impl CloneShimBuilder<'tcx> { // BB #7 (cleanup) // `drop(dest[beg])`; self.block(vec![], TerminatorKind::Drop { - location: self.tcx.mk_place_index(dest, beg), + location: dest.index(beg), target: BasicBlock::new(8), unwind: None, }, true); @@ -648,9 +645,9 @@ impl CloneShimBuilder<'tcx> { let mut previous_field = None; for (i, ity) in tys.enumerate() { let field = Field::new(i); - let src_field = self.tcx.mk_place_field(src.clone(), field, ity); + let src_field = src.clone().field(field, ity); - let dest_field = self.tcx.mk_place_field(dest.clone(), field, ity); + let dest_field = dest.clone().field(field, ity); // #(2i + 1) is the cleanup block for the previous clone operation let cleanup_block = self.block_index_offset(1); @@ -721,14 +718,14 @@ fn build_call_shim<'tcx>( let rcvr = match rcvr_adjustment { Adjustment::Identity => Operand::Move(rcvr_l), - Adjustment::Deref => Operand::Copy(tcx.mk_place_deref(rcvr_l)), + Adjustment::Deref => Operand::Copy(rcvr_l.deref()), Adjustment::DerefMove => { // fn(Self, ...) -> fn(*mut Self, ...) let arg_ty = local_decls[rcvr_arg].ty; 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(tcx.mk_place_deref(rcvr_l)) + Operand::Move(rcvr_l.deref()) } Adjustment::RefMut => { // let rcvr = &mut rcvr; @@ -772,7 +769,7 @@ fn build_call_shim<'tcx>( if let Some(untuple_args) = untuple_args { args.extend(untuple_args.iter().enumerate().map(|(i, ity)| { let arg_place = Place::from(Local::new(1+1)); - Operand::Move(tcx.mk_place_field(arg_place, Field::new(i), *ity)) + Operand::Move(arg_place.field(Field::new(i), *ity)) })); } else { args.extend((1..sig.inputs().len()).map(|i| { @@ -901,7 +898,6 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> { )), AggregateKind::Adt(adt_def, variant_index, substs, None, None), source_info, - tcx, ).collect(); let start_block = BasicBlockData { diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index bf3df1ae2fd84..15ecc6c37920b 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -1,6 +1,6 @@ use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use crate::transform::{MirPass, MirSource}; #[derive(PartialEq)] diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index c8605e22e1084..d9d0ce1855573 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -3,7 +3,7 @@ use rustc::mir::*; use rustc::mir::interpret::ConstValue; use rustc::ty::{self, Ty}; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use syntax_pos::DUMMY_SP; use super::Item as ConstCx; @@ -27,9 +27,6 @@ impl QualifSet { pub trait Qualif { const IDX: usize; - /// The name of the file used to debug the dataflow analysis that computes this qualif. - const ANALYSIS_NAME: &'static str; - /// Whether this `Qualif` is cleared when a local is moved from. const IS_CLEARED_ON_MOVE: bool = false; @@ -164,8 +161,8 @@ pub trait Qualif { Rvalue::Ref(_, _, ref place) => { // Special-case reborrows to be more like a copy of the reference. - if let &[ref proj_base @ .., elem] = place.projection.as_ref() { - if ProjectionElem::Deref == elem { + 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.kind { return Self::in_place(cx, per_local, PlaceRef { @@ -210,7 +207,6 @@ pub struct HasMutInterior; impl Qualif for HasMutInterior { const IDX: usize = 0; - const ANALYSIS_NAME: &'static str = "flow_has_mut_interior"; fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { !ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) @@ -268,7 +264,6 @@ pub struct NeedsDrop; impl Qualif for NeedsDrop { const IDX: usize = 1; - const ANALYSIS_NAME: &'static str = "flow_needs_drop"; const IS_CLEARED_ON_MOVE: bool = true; fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs index fc9290d638018..2789693ecb6ec 100644 --- a/src/librustc_mir/transform/check_consts/resolver.rs +++ b/src/librustc_mir/transform/check_consts/resolver.rs @@ -5,7 +5,7 @@ use rustc::mir::visit::Visitor; use rustc::mir::{self, BasicBlock, Local, Location}; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use std::cell::RefCell; use std::marker::PhantomData; @@ -56,16 +56,16 @@ where fn assign_qualif_direct(&mut self, place: &mir::Place<'tcx>, value: bool) { debug_assert!(!place.is_indirect()); - match (value, place.as_ref()) { - (true, mir::PlaceRef { base: &mir::PlaceBase::Local(local), .. }) => { - self.qualifs_per_local.insert(local); + match (value, place) { + (true, mir::Place { base: mir::PlaceBase::Local(local), .. }) => { + self.qualifs_per_local.insert(*local); } // For now, we do not clear the qualif if a local is overwritten in full by // an unqualified rvalue (e.g. `y = 5`). This is to be consistent // with aggregates where we overwrite all fields with assignments, which would not // get this feature. - (false, mir::PlaceRef { base: &mir::PlaceBase::Local(_local), projection: &[] }) => { + (false, mir::Place { base: mir::PlaceBase::Local(_local), projection: box [] }) => { // self.qualifs_per_local.remove(*local); } @@ -101,10 +101,11 @@ where // If a local with no projections is moved from (e.g. `x` in `y = x`), record that // it no longer needs to be dropped. - if let mir::Operand::Move(place) = operand { - if let Some(local) = place.as_local() { - self.qualifs_per_local.remove(local); - } + if let mir::Operand::Move(mir::Place { + base: mir::PlaceBase::Local(local), + projection: box [], + }) = *operand { + self.qualifs_per_local.remove(local); } } @@ -207,8 +208,7 @@ where _qualif: PhantomData, }; let results = - dataflow::Engine::new(item.tcx, item.body, item.def_id, dead_unwinds, analysis) - .iterate_to_fixpoint(); + dataflow::Engine::new(item.body, dead_unwinds, analysis).iterate_to_fixpoint(); let cursor = dataflow::ResultsCursor::new(item.body, results); let mut qualifs_in_any_value_of_ty = BitSet::new_empty(item.body.local_decls.len()); @@ -308,7 +308,7 @@ where { type Idx = Local; - const NAME: &'static str = Q::ANALYSIS_NAME; + const NAME: &'static str = "flow_sensitive_qualif"; fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize { body.local_decls.len() diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 76a73adf03836..7e876dd1d9980 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -5,7 +5,7 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUs use rustc::mir::*; use rustc::ty::cast::CastTy; use rustc::ty::{self, TyCtxt}; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use rustc_target::spec::abi::Abi; use syntax::symbol::sym; use syntax_pos::Span; @@ -137,7 +137,7 @@ pub fn compute_indirectly_mutable_locals<'mir, 'tcx>( item.tcx, item.body, item.def_id, - &item.tcx.get_attrs(item.def_id), + &[], &dead_unwinds, old_dataflow::IndirectlyMutableLocals::new(item.tcx, item.body, item.param_env), |_, local| old_dataflow::DebugFormatted::new(&local), @@ -244,8 +244,8 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { if let Rvalue::Ref(_, kind, ref place) = *rvalue { // Special-case reborrows to be more like a copy of a reference. let mut reborrow_place = None; - if let &[ref proj_base @ .., elem] = place.projection.as_ref() { - if elem == ProjectionElem::Deref { + 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.kind { reborrow_place = Some(proj_base); @@ -376,15 +376,12 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { ); if rvalue_has_mut_interior { - let is_derived_from_illegal_borrow = match borrowed_place.as_local() { + let is_derived_from_illegal_borrow = match *borrowed_place { // If an unprojected local was borrowed and its value was the result of an // illegal borrow, suppress this error and mark the result of this borrow as // illegal as well. - Some(borrowed_local) - if self.derived_from_illegal_borrow.contains(borrowed_local) => - { - true - } + Place { base: PlaceBase::Local(borrowed_local), projection: box [] } + if self.derived_from_illegal_borrow.contains(borrowed_local) => true, // Otherwise proceed normally: check the legality of a mutable borrow in this // context. @@ -397,7 +394,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { // FIXME: should we also clear `derived_from_illegal_borrow` when a local is // assigned a new value? if is_derived_from_illegal_borrow { - if let Some(dest) = dest.as_local() { + if let Place { base: PlaceBase::Local(dest), projection: box [] } = *dest { self.derived_from_illegal_borrow.insert(dest); } } @@ -407,25 +404,25 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { self.super_assign(dest, rvalue, location); } - fn visit_projection_elem( + fn visit_projection( &mut self, place_base: &PlaceBase<'tcx>, - proj_base: &[PlaceElem<'tcx>], - elem: &PlaceElem<'tcx>, + proj: &[PlaceElem<'tcx>], context: PlaceContext, location: Location, ) { trace!( - "visit_projection_elem: place_base={:?} proj_base={:?} elem={:?} \ - context={:?} location={:?}", - place_base, - proj_base, - elem, + "visit_place_projection: proj={:?} context={:?} location={:?}", + proj, context, location, ); + self.super_projection(place_base, proj, context, location); - self.super_projection_elem(place_base, proj_base, elem, context, location); + let (elem, proj_base) = match proj.split_last() { + Some(x) => x, + None => return, + }; match elem { ProjectionElem::Deref => { @@ -470,6 +467,8 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { self.qualifs.needs_drop.visit_statement(statement, location); self.qualifs.has_mut_interior.visit_statement(statement, location); + debug!("needs_drop: {:?}", self.qualifs.needs_drop.get()); + debug!("has_mut_interior: {:?}", self.qualifs.has_mut_interior.get()); match statement.kind { StatementKind::Assign(..) => { @@ -495,6 +494,8 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { self.qualifs.needs_drop.visit_terminator(terminator, location); self.qualifs.has_mut_interior.visit_terminator(terminator, location); + debug!("needs_drop: {:?}", self.qualifs.needs_drop.get()); + debug!("has_mut_interior: {:?}", self.qualifs.has_mut_interior.get()); self.super_terminator(terminator, location); } @@ -574,7 +575,10 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { return; } - let needs_drop = if let Some(local) = dropped_place.as_local() { + let needs_drop = if let Place { + base: PlaceBase::Local(local), + projection: box [], + } = *dropped_place { // Use the span where the local was declared as the span of the drop error. err_span = self.body.local_decls[local].source_info.span; self.qualifs.needs_drop.contains(local) diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index d9b983ab790c2..acd53ac68ae3f 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fx::FxHashSet; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::Lrc; use rustc::ty::query::Providers; @@ -12,7 +12,7 @@ use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSA use rustc::mir::*; use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext}; -use syntax::symbol::{Symbol, sym}; +use syntax::symbol::{InternedString, sym}; use std::ops::Bound; @@ -167,8 +167,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { (CastTy::FnPtr, CastTy::Int(_)) => { self.register_violations(&[UnsafetyViolation { source_info: self.source_info, - description: Symbol::intern("cast of pointer to int"), - details: Symbol::intern("casting pointers to integers in constants"), + description: InternedString::intern("cast of pointer to int"), + details: InternedString::intern( + "casting pointers to integers in constants"), kind: UnsafetyViolationKind::General, }], &[]); }, @@ -184,8 +185,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind { self.register_violations(&[UnsafetyViolation { source_info: self.source_info, - description: Symbol::intern("pointer operation"), - details: Symbol::intern("operations on pointers in constants"), + description: InternedString::intern("pointer operation"), + details: InternedString::intern("operations on pointers in constants"), kind: UnsafetyViolationKind::General, }], &[]); } @@ -218,8 +219,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.source_scope_local_data[source_info.scope].lint_root; self.register_violations(&[UnsafetyViolation { source_info, - description: Symbol::intern("use of extern static"), - details: Symbol::intern( + 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"), @@ -239,8 +240,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.source_scope_local_data[source_info.scope].lint_root; self.register_violations(&[UnsafetyViolation { source_info, - description: Symbol::intern("borrow of packed field"), - details: Symbol::intern( + 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"), @@ -333,8 +334,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { let source_info = self.source_info; self.register_violations(&[UnsafetyViolation { source_info, - description: Symbol::intern(description), - details: Symbol::intern(details), + description: InternedString::intern(description), + details: InternedString::intern(details), kind, }], &[]); } @@ -406,8 +407,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { place: &Place<'tcx>, is_mut_use: bool, ) { - let mut cursor = place.projection.as_ref(); - while let &[ref proj_base @ .., elem] = cursor { + let mut cursor = &*place.projection; + while let [proj_base @ .., elem] = cursor { cursor = proj_base; match elem { @@ -437,8 +438,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { let source_info = self.source_info; self.register_violations(&[UnsafetyViolation { source_info, - description: Symbol::intern(description), - details: Symbol::intern(details), + description: InternedString::intern(description), + details: InternedString::intern(details), kind: UnsafetyViolationKind::GeneralAndConstFn, }], &[]); } diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index 4fd4fe45cd4f1..ea173279aa073 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -24,22 +24,16 @@ use crate::transform::{MirPass, MirSource}; pub struct CleanupNonCodegenStatements; -pub struct DeleteNonCodegenStatements<'tcx> { - tcx: TyCtxt<'tcx>, -} +pub struct DeleteNonCodegenStatements; impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { - let mut delete = DeleteNonCodegenStatements { tcx }; + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { + let mut delete = DeleteNonCodegenStatements; delete.visit_body(body); } } -impl<'tcx> MutVisitor<'tcx> for DeleteNonCodegenStatements<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - +impl<'tcx> MutVisitor<'tcx> for DeleteNonCodegenStatements { fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) { diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 13097a2156167..612822b6d9d34 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -7,9 +7,10 @@ use std::cell::Cell; use rustc::hir::def::DefKind; use rustc::hir::def_id::DefId; use rustc::mir::{ - AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, Local, UnOp, - StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, - BinOp, SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock, + AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, + Local, NullOp, UnOp, StatementKind, Statement, LocalKind, + TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, + SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock, }; use rustc::mir::visit::{ Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext, @@ -20,7 +21,7 @@ use syntax::ast::Mutability; use syntax_pos::{Span, DUMMY_SP}; use rustc::ty::subst::InternalSubsts; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc::ty::layout::{ LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, }; @@ -117,7 +118,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { struct ConstPropMachine; impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { - type MemoryKinds = !; + type MemoryKinds= !; type PointerTag = (); type ExtraFnVal = !; @@ -334,9 +335,34 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } fn get_const(&self, local: Local) -> Option> { + let l = &self.ecx.frame().locals[local]; + + // If the local is `Unitialized` or `Dead` then we haven't propagated a value into it. + // + // `InterpCx::access_local()` mostly takes care of this for us however, for ZSTs, + // it will synthesize a value for us. In doing so, that will cause the + // `get_const(l).is_empty()` assert right before we call `set_const()` in `visit_statement` + // to fail. + if let LocalValue::Uninitialized | LocalValue::Dead = l.value { + return None; + } + self.ecx.access_local(self.ecx.frame(), local, None).ok() } + fn set_const(&mut self, local: Local, c: Const<'tcx>) { + let frame = self.ecx.frame_mut(); + + if let Some(layout) = frame.locals[local].layout.get() { + debug_assert_eq!(c.layout, layout); + } + + frame.locals[local] = LocalState { + value: LocalValue::Live(*c), + layout: Cell::new(Some(c.layout)), + }; + } + fn remove_const(&mut self, local: Local) { self.ecx.frame_mut().locals[local] = LocalState { value: LocalValue::Uninitialized, @@ -430,26 +456,35 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { place_layout: TyLayout<'tcx>, source_info: SourceInfo, place: &Place<'tcx>, - ) -> Option<()> { + ) -> Option> { let span = source_info.span; - let overflow_check = self.tcx.sess.overflow_checks(); - - // Perform any special handling for specific Rvalue types. - // Generally, checks here fall into one of two categories: - // 1. Additional checking to provide useful lints to the user - // - In this case, we will do some validation and then fall through to the - // end of the function which evals the assignment. - // 2. Working around bugs in other parts of the compiler - // - In this case, we'll return `None` from this function to stop evaluation. + // if this isn't a supported operation, then return None match rvalue { - // Additional checking: if overflow checks are disabled (which is usually the case in - // release mode), then we need to do additional checking here to give lints to the user - // if an overflow would occur. - Rvalue::UnaryOp(UnOp::Neg, arg) if !overflow_check => { - trace!("checking UnaryOp(op = Neg, arg = {:?})", arg); + Rvalue::Repeat(..) | + Rvalue::Aggregate(..) | + Rvalue::NullaryOp(NullOp::Box, _) | + Rvalue::Discriminant(..) => return None, + + Rvalue::Use(_) | + Rvalue::Len(_) | + Rvalue::Cast(..) | + Rvalue::NullaryOp(..) | + Rvalue::CheckedBinaryOp(..) | + Rvalue::Ref(..) | + Rvalue::UnaryOp(..) | + Rvalue::BinaryOp(..) => { } + } + + // perform any special checking for specific Rvalue types + if let Rvalue::UnaryOp(op, arg) = rvalue { + trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg); + let overflow_check = self.tcx.sess.overflow_checks(); - self.use_ecx(source_info, |this| { + self.use_ecx(source_info, |this| { + // We check overflow in debug mode already + // so should only check in release mode. + if *op == UnOp::Neg && !overflow_check { let ty = arg.ty(&this.local_decls, this.tcx); if ty.is_integral() { @@ -461,94 +496,76 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { throw_panic!(OverflowNeg) } } - - Ok(()) - })?; - } - - // Additional checking: check for overflows on integer binary operations and report - // them to the user as lints. - Rvalue::BinaryOp(op, left, right) => { - trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); - - let r = self.use_ecx(source_info, |this| { - this.ecx.read_immediate(this.ecx.eval_operand(right, None)?) - })?; - if *op == BinOp::Shr || *op == BinOp::Shl { - let left_bits = place_layout.size.bits(); - let right_size = r.layout.size; - let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); - if r_bits.ok().map_or(false, |b| b >= left_bits as u128) { - let source_scope_local_data = match self.source_scope_local_data { - ClearCrossCrate::Set(ref data) => data, - ClearCrossCrate::Clear => return None, - }; - let dir = if *op == BinOp::Shr { - "right" - } else { - "left" - }; - let hir_id = source_scope_local_data[source_info.scope].lint_root; - self.tcx.lint_hir( - ::rustc::lint::builtin::EXCEEDING_BITSHIFTS, - hir_id, - span, - &format!("attempt to shift {} with overflow", dir)); - return None; - } } - // If overflow checking is enabled (like in debug mode by default), - // then we'll already catch overflow when we evaluate the `Assert` statement - // in MIR. However, if overflow checking is disabled, then there won't be any - // `Assert` statement and so we have to do additional checking here. - if !overflow_check { - self.use_ecx(source_info, |this| { - let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; - let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?; - - if overflow { - let err = err_panic!(Overflow(*op)).into(); - return Err(err); - } - - Ok(()) - })?; + Ok(()) + })?; + } else if let Rvalue::BinaryOp(op, left, right) = rvalue { + trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); + + let r = self.use_ecx(source_info, |this| { + this.ecx.read_immediate(this.ecx.eval_operand(right, None)?) + })?; + if *op == BinOp::Shr || *op == BinOp::Shl { + let left_bits = place_layout.size.bits(); + let right_size = r.layout.size; + let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); + if r_bits.ok().map_or(false, |b| b >= left_bits as u128) { + let source_scope_local_data = match self.source_scope_local_data { + ClearCrossCrate::Set(ref data) => data, + ClearCrossCrate::Clear => return None, + }; + let dir = if *op == BinOp::Shr { + "right" + } else { + "left" + }; + let hir_id = source_scope_local_data[source_info.scope].lint_root; + self.tcx.lint_hir( + ::rustc::lint::builtin::EXCEEDING_BITSHIFTS, + hir_id, + span, + &format!("attempt to shift {} with overflow", dir)); + return None; } } + self.use_ecx(source_info, |this| { + let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; + let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?; + + // We check overflow in debug mode already + // so should only check in release mode. + if !this.tcx.sess.overflow_checks() && overflow { + let err = err_panic!(Overflow(*op)).into(); + return Err(err); + } - // Work around: avoid ICE in miri. FIXME(wesleywiser) - // The Miri engine ICEs when taking a reference to an uninitialized unsized - // local. There's nothing it can do here: taking a reference needs an allocation - // which needs to know the size. Normally that's okay as during execution - // (e.g. for CTFE) it can never happen. But here in const_prop - // unknown data is uninitialized, so if e.g. a function argument is unsized - // and has a reference taken, we get an ICE. - Rvalue::Ref(_, _, place_ref) => { - trace!("checking Ref({:?})", place_ref); - - if let Some(local) = place_ref.as_local() { - let alive = - if let LocalValue::Live(_) = self.ecx.frame().locals[local].value { - true - } else { - false - }; - - if !alive { - trace!("skipping Ref({:?}) to uninitialized local", place); - return None; - } + Ok(()) + })?; + } else if let Rvalue::Ref(_, _, place) = rvalue { + trace!("checking Ref({:?})", place); + // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref + // from a function argument that hasn't been assigned to in this function. + if let Place { + base: PlaceBase::Local(local), + projection: box [] + } = place { + let alive = + if let LocalValue::Live(_) = self.ecx.frame().locals[*local].value { + true + } else { false }; + + if local.as_usize() <= self.ecx.frame().body.arg_count && !alive { + trace!("skipping Ref({:?})", place); + return None; } } - - _ => { } } self.use_ecx(source_info, |this| { trace!("calling eval_rvalue_into_place(rvalue = {:?}, place = {:?})", rvalue, place); this.ecx.eval_rvalue_into_place(rvalue, place)?; - Ok(()) + this.ecx.eval_place_to_op(place, Some(place_layout)) }) } @@ -687,10 +704,6 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { } impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - fn visit_constant( &mut self, constant: &mut Constant<'tcx>, @@ -712,25 +725,28 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { .ty(&self.local_decls, self.tcx) .ty; if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) { - if let Some(local) = place.as_local() { - let source = statement.source_info; - if let Some(()) = self.const_prop(rval, place_layout, source, place) { + if let Place { + base: PlaceBase::Local(local), + projection: box [], + } = *place { + if let Some(value) = self.const_prop(rval, + place_layout, + statement.source_info, + place) { + trace!("checking whether {:?} can be stored to {:?}", value, local); if self.can_const_prop[local] { - trace!("propagated into {:?}", local); + trace!("storing {:?} to {:?}", value, local); + assert!(self.get_const(local).is_none() || + self.get_const(local) == Some(value)); + self.set_const(local, value); if self.should_const_prop() { - let value = - self.get_const(local).expect("local was dead/uninitialized"); - trace!("replacing {:?} with {:?}", rval, value); self.replace_with_const( rval, value, statement.source_info, ); } - } else { - trace!("can't propagate into {:?}", local); - self.remove_const(local); } } } diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index 4c26feac4af79..28f97f41b50cf 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -19,7 +19,9 @@ //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the //! future. -use rustc::mir::{Constant, Local, LocalKind, Location, Place, Body, Operand, Rvalue, StatementKind}; +use rustc::mir::{ + Constant, Local, LocalKind, Location, Place, PlaceBase, Body, Operand, Rvalue, StatementKind +}; use rustc::mir::visit::MutVisitor; use rustc::ty::TyCtxt; use crate::transform::{MirPass, MirSource}; @@ -90,32 +92,28 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { }; // That use of the source must be an assignment. - match &statement.kind { - StatementKind::Assign(box(place, Rvalue::Use(operand))) => { - if let Some(local) = place.as_local() { - if local == dest_local { - let maybe_action = match operand { - Operand::Copy(ref src_place) | - Operand::Move(ref src_place) => { - Action::local_copy(&body, &def_use_analysis, src_place) - } - Operand::Constant(ref src_constant) => { - Action::constant(src_constant) - } - }; - match maybe_action { - Some(this_action) => action = this_action, - None => continue, - } - } else { - debug!(" Can't copy-propagate local: source use is not an \ - assignment"); - continue + match statement.kind { + StatementKind::Assign( + 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) | + Operand::Move(ref src_place) => { + Action::local_copy(&body, &def_use_analysis, src_place) } - } else { - debug!(" Can't copy-propagate local: source use is not an \ - assignment"); - continue + Operand::Constant(ref src_constant) => { + Action::constant(src_constant) + } + }; + match maybe_action { + Some(this_action) => action = this_action, + None => continue, } } _ => { @@ -126,8 +124,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { } } - changed = - action.perform(body, &def_use_analysis, dest_local, location, tcx) || changed; + changed = action.perform(body, &def_use_analysis, dest_local, location) || changed; // FIXME(pcwalton): Update the use-def chains to delete the instructions instead of // regenerating the chains. break @@ -151,20 +148,31 @@ fn eliminate_self_assignments( for def in dest_use_info.defs_not_including_drop() { let location = def.location; if let Some(stmt) = body[location.block].statements.get(location.statement_index) { - match &stmt.kind { - StatementKind::Assign(box (place, Rvalue::Use(Operand::Copy(src_place)))) - | StatementKind::Assign(box (place, Rvalue::Use(Operand::Move(src_place)))) => { - if let (Some(local), Some(src_local)) = - (place.as_local(), src_place.as_local()) - { - if local == dest_local && dest_local == src_local { - } else { - continue; - } - } else { - continue; - } - } + match stmt.kind { + StatementKind::Assign( + box( + Place { + base: PlaceBase::Local(local), + projection: box [], + }, + Rvalue::Use(Operand::Copy(Place { + base: PlaceBase::Local(src_local), + projection: box [], + })), + ) + ) | + StatementKind::Assign( + 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; } @@ -190,7 +198,10 @@ impl<'tcx> Action<'tcx> { fn local_copy(body: &Body<'tcx>, def_use_analysis: &DefUseAnalysis, src_place: &Place<'tcx>) -> Option> { // The source must be a local. - let src_local = if let Some(local) = src_place.as_local() { + let src_local = if let Place { + base: PlaceBase::Local(local), + projection: box [], + } = *src_place { local } else { debug!(" Can't copy-propagate local: source is not a local"); @@ -245,8 +256,7 @@ impl<'tcx> Action<'tcx> { body: &mut Body<'tcx>, def_use_analysis: &DefUseAnalysis, dest_local: Local, - location: Location, - tcx: TyCtxt<'tcx>) + location: Location) -> bool { match self { Action::PropagateLocalCopy(src_local) => { @@ -270,7 +280,7 @@ impl<'tcx> Action<'tcx> { } // Replace all uses of the destination local with the source local. - def_use_analysis.replace_all_defs_and_uses_with(dest_local, body, src_local, tcx); + def_use_analysis.replace_all_defs_and_uses_with(dest_local, body, src_local); // Finally, zap the now-useless assignment instruction. debug!(" Deleting assignment"); @@ -294,8 +304,7 @@ impl<'tcx> Action<'tcx> { // Replace all uses of the destination local with the constant. let mut visitor = ConstantPropagationVisitor::new(dest_local, - src_constant, - tcx); + src_constant); for dest_place_use in &dest_local_info.defs_and_uses { visitor.visit_location(body, dest_place_use.location) } @@ -327,42 +336,33 @@ impl<'tcx> Action<'tcx> { struct ConstantPropagationVisitor<'tcx> { dest_local: Local, constant: Constant<'tcx>, - tcx: TyCtxt<'tcx>, uses_replaced: usize, } impl<'tcx> ConstantPropagationVisitor<'tcx> { - fn new(dest_local: Local, constant: Constant<'tcx>, tcx: TyCtxt<'tcx>) + fn new(dest_local: Local, constant: Constant<'tcx>) -> ConstantPropagationVisitor<'tcx> { ConstantPropagationVisitor { dest_local, constant, - tcx, uses_replaced: 0, } } } impl<'tcx> MutVisitor<'tcx> for ConstantPropagationVisitor<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) { self.super_operand(operand, location); - match operand { - Operand::Copy(place) | - Operand::Move(place) => { - if let Some(local) = place.as_local() { - if local == self.dest_local { - } else { - return; - } - } else { - return; - } - } + match *operand { + Operand::Copy(Place { + base: PlaceBase::Local(local), + projection: box [], + }) | + Operand::Move(Place { + base: PlaceBase::Local(local), + 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 cdde9e12edcbb..c1224be6324e2 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -45,7 +45,6 @@ impl<'tcx> MirPass<'tcx> for Deaggregator { }), *kind, source_info, - tcx, )) }); } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index f91a08bcd9aa6..d7b6810a8659a 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -14,7 +14,7 @@ use rustc::ty::layout::VariantIdx; use rustc::hir; use rustc::mir::*; use rustc::util::nodemap::FxHashMap; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use std::fmt; use syntax_pos::Span; diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index b30e2de4ca0bc..21ca339eb968b 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -23,12 +23,9 @@ impl EraseRegionsVisitor<'tcx> { } impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) { *ty = self.tcx.erase_regions(ty); + self.super_ty(ty); } fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) { @@ -43,19 +40,10 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { *substs = self.tcx.erase_regions(substs); } - fn process_projection_elem( - &mut self, - elem: &PlaceElem<'tcx>, - ) -> Option> { - if let PlaceElem::Field(field, ty) = elem { - let new_ty = self.tcx.erase_regions(ty); - - if new_ty != *ty { - return Some(PlaceElem::Field(*field, new_ty)); - } - } - - None + fn visit_statement(&mut self, + statement: &mut Statement<'tcx>, + location: Location) { + self.super_statement(statement, location); } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 911901be36b24..2b66e602370cc 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -58,8 +58,8 @@ use rustc::ty::GeneratorSubsts; use rustc::ty::layout::VariantIdx; use rustc::ty::subst::SubstsRef; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::{Idx, IndexVec}; -use rustc_index::bit_set::{BitSet, BitMatrix}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_data_structures::bit_set::{BitSet, BitMatrix}; use std::borrow::Cow; use std::iter; use std::mem; @@ -74,17 +74,12 @@ use crate::util::liveness; pub struct StateTransform; -struct RenameLocalVisitor<'tcx> { +struct RenameLocalVisitor { from: Local, to: Local, - tcx: TyCtxt<'tcx>, } -impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - +impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor { fn visit_local(&mut self, local: &mut Local, _: PlaceContext, @@ -93,29 +88,11 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor<'tcx> { *local = self.to; } } - - fn process_projection_elem( - &mut self, - elem: &PlaceElem<'tcx>, - ) -> Option> { - match elem { - PlaceElem::Index(local) if *local == self.from => { - Some(PlaceElem::Index(self.to)) - } - _ => None, - } - } } -struct DerefArgVisitor<'tcx> { - tcx: TyCtxt<'tcx>, -} - -impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } +struct DerefArgVisitor; +impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor { fn visit_local(&mut self, local: &mut Local, _: PlaceContext, @@ -130,30 +107,19 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> { if place.base == PlaceBase::Local(self_arg()) { replace_base(place, Place { base: PlaceBase::Local(self_arg()), - projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Deref]), - }, self.tcx); + projection: Box::new([ProjectionElem::Deref]), + }); } else { - self.visit_place_base(&mut place.base, context, location); - - for elem in place.projection.iter() { - if let PlaceElem::Index(local) = elem { - assert_ne!(*local, self_arg()); - } - } + self.super_place(place, context, location); } } } struct PinArgVisitor<'tcx> { ref_gen_ty: Ty<'tcx>, - tcx: TyCtxt<'tcx>, } impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - fn visit_local(&mut self, local: &mut Local, _: PlaceContext, @@ -161,38 +127,28 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { assert_ne!(*local, self_arg()); } - fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { + fn visit_place(&mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location) { if place.base == PlaceBase::Local(self_arg()) { - replace_base( - place, - Place { - base: PlaceBase::Local(self_arg()), - projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Field( - Field::new(0), - self.ref_gen_ty, - )]), - }, - self.tcx, - ); + replace_base(place, Place { + base: PlaceBase::Local(self_arg()), + projection: Box::new([ProjectionElem::Field(Field::new(0), self.ref_gen_ty)]), + }); } else { - self.visit_place_base(&mut place.base, context, location); - - for elem in place.projection.iter() { - if let PlaceElem::Index(local) = elem { - assert_ne!(*local, self_arg()); - } - } + self.super_place(place, context, location); } } } -fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtxt<'tcx>) { +fn replace_base(place: &mut Place<'tcx>, new_base: Place<'tcx>) { place.base = new_base.base; let mut new_projection = new_base.projection.to_vec(); new_projection.append(&mut place.projection.to_vec()); - place.projection = tcx.intern_place_elems(&new_projection); + place.projection = new_projection.into_boxed_slice(); } fn self_arg() -> Local { @@ -246,13 +202,13 @@ impl TransformVisitor<'tcx> { // Create a Place referencing a generator struct field fn make_field(&self, variant_index: VariantIdx, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> { let self_place = Place::from(self_arg()); - let base = self.tcx.mk_place_downcast_unnamed(self_place, variant_index); + let base = self_place.downcast_unnamed(variant_index); let mut projection = base.projection.to_vec(); projection.push(ProjectionElem::Field(Field::new(idx), ty)); Place { base: base.base, - projection: self.tcx.intern_place_elems(&projection), + projection: projection.into_boxed_slice(), } } @@ -284,10 +240,6 @@ impl TransformVisitor<'tcx> { } impl MutVisitor<'tcx> for TransformVisitor<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - fn visit_local(&mut self, local: &mut Local, _: PlaceContext, @@ -295,25 +247,17 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { assert_eq!(self.remap.get(local), None); } - fn visit_place( - &mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location, - ) { + fn visit_place(&mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location) { if let PlaceBase::Local(l) = place.base { // Replace an Local in the remap with a generator struct access if let Some(&(ty, variant_index, idx)) = self.remap.get(&l) { - replace_base(place, self.make_field(variant_index, idx, ty), self.tcx); + replace_base(place, self.make_field(variant_index, idx, ty)); } } else { - self.visit_place_base(&mut place.base, context, location); - - for elem in place.projection.iter() { - if let PlaceElem::Index(local) = elem { - assert_ne!(*local, self_arg()); - } - } + self.super_place(place, context, location); } } @@ -399,7 +343,7 @@ fn make_generator_state_argument_indirect<'tcx>( body.local_decls.raw[1].ty = ref_gen_ty; // Add a deref to accesses of the generator state - DerefArgVisitor { tcx }.visit_body(body); + DerefArgVisitor.visit_body(body); } fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -414,13 +358,12 @@ fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body body.local_decls.raw[1].ty = pin_ref_gen_ty; // Add the Pin field access to accesses of the generator state - PinArgVisitor { ref_gen_ty, tcx }.visit_body(body); + PinArgVisitor { ref_gen_ty }.visit_body(body); } fn replace_result_variable<'tcx>( ret_ty: Ty<'tcx>, body: &mut Body<'tcx>, - tcx: TyCtxt<'tcx>, ) -> Local { let source_info = source_info(body); let new_ret = LocalDecl { @@ -441,7 +384,6 @@ fn replace_result_variable<'tcx>( RenameLocalVisitor { from: RETURN_PLACE, to: new_ret_local, - tcx, }.visit_body(body); new_ret_local @@ -566,7 +508,10 @@ fn locals_live_across_suspend_points( storage_liveness_map.insert(block, storage_liveness.clone()); requires_storage_cursor.seek(loc); - let storage_required = requires_storage_cursor.get().clone(); + let mut storage_required = requires_storage_cursor.get().clone(); + + // Mark locals without storage statements as always requiring storage + storage_required.union(&ignored.0); // Locals live are live at this point only if they are used across // suspension points (the `liveness` variable) @@ -890,24 +835,17 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut for (block, block_data) in body.basic_blocks().iter_enumerated() { let (target, unwind, source_info) = match block_data.terminator() { - Terminator { + &Terminator { source_info, kind: TerminatorKind::Drop { - location, + location: Place { + base: PlaceBase::Local(local), + projection: box [], + }, target, unwind } - } => { - if let Some(local) = location.as_local() { - if local == gen { - (target, unwind, source_info) - } else { - continue; - } - } else { - continue; - } - } + } if local == gen => (target, unwind, source_info), _ => continue, }; let unwind = if block_data.is_cleanup { @@ -917,10 +855,10 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut }; elaborate_drop( &mut elaborator, - *source_info, + source_info, &Place::from(gen), (), - *target, + target, unwind, block, ); @@ -1188,7 +1126,6 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // Get the interior types and substs which typeck computed let (upvars, interior, discr_ty, movable) = match gen_ty.kind { ty::Generator(_, substs, movability) => { - let substs = substs.as_generator(); (substs.upvar_tys(def_id, tcx).collect(), substs.witness(def_id, tcx), substs.discr_ty(tcx), @@ -1208,7 +1145,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // We rename RETURN_PLACE which has type mir.return_ty to new_ret_local // RETURN_PLACE then is a fresh unused local with type ret_ty. - let new_ret_local = replace_result_variable(ret_ty, body, tcx); + let new_ret_local = replace_result_variable(ret_ty, body); // Extract locals which are live across suspension point into `layout` // `remap` gives a mapping from local indices onto generator struct indices diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 5a34e3f471f66..7f56c6f7986aa 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -3,8 +3,8 @@ use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::DefId; -use rustc_index::bit_set::BitSet; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::bit_set::BitSet; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::*; use rustc::mir::visit::*; @@ -461,7 +461,7 @@ impl Inliner<'tcx> { }; caller_body[callsite.bb] .statements.push(stmt); - self.tcx.mk_place_deref(tmp) + tmp.deref() } else { destination.0 }; @@ -481,7 +481,6 @@ impl Inliner<'tcx> { return_block, cleanup_block: cleanup, in_cleanup_block: false, - tcx: self.tcx, }; @@ -560,8 +559,7 @@ impl Inliner<'tcx> { let tuple_tmp_args = tuple_tys.iter().enumerate().map(|(i, ty)| { // This is e.g., `tuple_tmp.0` in our example above. - let tuple_field = Operand::Move(tcx.mk_place_field( - tuple.clone(), + let tuple_field = Operand::Move(tuple.clone().field( Field::new(i), ty.expect_ty(), )); @@ -589,12 +587,13 @@ impl Inliner<'tcx> { // FIXME: Analysis of the usage of the arguments to avoid // unnecessary temporaries. - if let Operand::Move(place) = &arg { - if let Some(local) = place.as_local() { - if caller_body.local_kind(local) == LocalKind::Temp { - // Reuse the operand if it's a temporary already - return local; - } + if let Operand::Move(Place { + base: PlaceBase::Local(local), + projection: box [], + }) = arg { + if caller_body.local_kind(local) == LocalKind::Temp { + // Reuse the operand if it's a temporary already + return local; } } @@ -640,7 +639,6 @@ struct Integrator<'a, 'tcx> { return_block: BasicBlock, cleanup_block: Option, in_cleanup_block: bool, - tcx: TyCtxt<'tcx>, } impl<'a, 'tcx> Integrator<'a, 'tcx> { @@ -649,65 +647,48 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> { debug!("updating target `{:?}`, new: `{:?}`", tgt, new); new } +} - fn make_integrate_local(&self, local: &Local) -> Local { +impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { + fn visit_local(&mut self, + local: &mut Local, + _ctxt: PlaceContext, + _location: Location) { if *local == RETURN_PLACE { - match self.destination.as_local() { - Some(l) => return l, - ref place => bug!("Return place is {:?}, not local", place), + match self.destination { + Place { + base: PlaceBase::Local(l), + projection: box [], + } => { + *local = l; + return; + }, + ref place => bug!("Return place is {:?}, not local", place) } } - let idx = local.index() - 1; if idx < self.args.len() { - return self.args[idx]; - } - - self.local_map[Local::new(idx - self.args.len())] - } -} - -impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn visit_local( - &mut self, - local: &mut Local, - _ctxt: PlaceContext, - _location: Location, - ) { - *local = self.make_integrate_local(local); - } - - fn visit_place( - &mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location, - ) { - if let Some(RETURN_PLACE) = place.as_local() { - // Return pointer; update the place itself - *place = self.destination.clone(); - } else { - self.super_place(place, context, location); + *local = self.args[idx]; + return; } + *local = self.local_map[Local::new(idx - self.args.len())]; } - fn process_projection_elem( - &mut self, - elem: &PlaceElem<'tcx>, - ) -> Option> { - if let PlaceElem::Index(local) = elem { - let new_local = self.make_integrate_local(local); - - if new_local != *local { - return Some(PlaceElem::Index(new_local)) - } + fn visit_place(&mut self, + place: &mut Place<'tcx>, + _ctxt: PlaceContext, + _location: Location) { + + match place { + Place { + base: PlaceBase::Local(RETURN_PLACE), + projection: box [], + } => { + // Return pointer; update the place itself + *place = self.destination.clone(); + }, + _ => self.super_place(place, _ctxt, _location) } - - None } fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) { diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index a567ed668bfa5..6b609e25ec042 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -1,12 +1,11 @@ //! Performs various peephole optimizations. -use rustc::mir::{ - Constant, Location, Place, PlaceBase, PlaceRef, Body, Operand, ProjectionElem, Rvalue, Local -}; +use rustc::mir::{Constant, Location, Place, PlaceBase, Body, Operand, ProjectionElem, Rvalue, + Local}; use rustc::mir::visit::{MutVisitor, Visitor}; use rustc::ty::{self, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use std::mem; use crate::transform::{MirPass, MirSource}; @@ -29,33 +28,32 @@ impl<'tcx> MirPass<'tcx> for InstCombine { }; // Then carry out those optimizations. - MutVisitor::visit_body(&mut InstCombineVisitor { optimizations, tcx }, body); + MutVisitor::visit_body(&mut InstCombineVisitor { optimizations }, body); } } pub struct InstCombineVisitor<'tcx> { optimizations: OptimizationList<'tcx>, - tcx: TyCtxt<'tcx>, } impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) { if self.optimizations.and_stars.remove(&location) { debug!("replacing `&*`: {:?}", rvalue); - let new_place = match rvalue { - Rvalue::Ref(_, _, place) => { - if let &[ref proj_l @ .., proj_r] = place.projection.as_ref() { - place.projection = self.tcx().intern_place_elems(&vec![proj_r.clone()]); - - Place { + let new_place = match *rvalue { + Rvalue::Ref(_, _, Place { + ref mut base, + projection: ref mut projection @ box [.., _], + }) => { + if let box [proj_l @ .., proj_r] = projection { + let place = Place { // Replace with dummy - base: mem::replace(&mut place.base, PlaceBase::Local(Local::new(0))), - projection: self.tcx().intern_place_elems(proj_l), - } + 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!(); } @@ -93,14 +91,12 @@ 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) = rvalue { - if let PlaceRef { - base, - projection: &[ref proj_base @ .., ProjectionElem::Deref], - } = place.as_ref() { - if Place::ty_from(base, proj_base, self.body, self.tcx).ty.is_region_ptr() { - self.optimizations.and_stars.insert(location); - } + if let Rvalue::Ref(_, _, Place { + 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); } } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index dbe6c7845926d..5037c791cb688 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -1,5 +1,5 @@ use crate::{build, shim}; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::mir::{Body, MirPhase, Promoted}; use rustc::ty::{TyCtxt, InstanceDef}; @@ -228,7 +228,7 @@ fn run_optimization_passes<'tcx>( ) { run_passes(tcx, body, InstanceDef::Item(def_id), promoted, MirPhase::Optimized, &[ // Remove all things only needed by analysis - &no_landing_pads::NoLandingPads::new(tcx), + &no_landing_pads::NoLandingPads, &simplify_branches::SimplifyBranches::new("initial"), &remove_noop_landing_pads::RemoveNoopLandingPads, &cleanup_post_borrowck::CleanupNonCodegenStatements, @@ -238,7 +238,7 @@ fn run_optimization_passes<'tcx>( // These next passes must be executed together &add_call_guards::CriticalCallEdges, &elaborate_drops::ElaborateDrops, - &no_landing_pads::NoLandingPads::new(tcx), + &no_landing_pads::NoLandingPads, // AddMovesForPackedDrops needs to run after drop // elaboration. &add_moves_for_packed_drops::AddMovesForPackedDrops, @@ -257,7 +257,7 @@ fn run_optimization_passes<'tcx>( // Optimizations begin. - &uniform_array_move_out::RestoreSubsliceArrayMoveOut::new(tcx), + &uniform_array_move_out::RestoreSubsliceArrayMoveOut, &inline::Inline, // Lowering generator control-flow and variables diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs index fbd14d9ef6170..762bb5d44839f 100644 --- a/src/librustc_mir/transform/no_landing_pads.rs +++ b/src/librustc_mir/transform/no_landing_pads.rs @@ -6,17 +6,9 @@ use rustc::mir::*; use rustc::mir::visit::MutVisitor; use crate::transform::{MirPass, MirSource}; -pub struct NoLandingPads<'tcx> { - tcx: TyCtxt<'tcx>, -} - -impl<'tcx> NoLandingPads<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> Self { - NoLandingPads { tcx } - } -} +pub struct NoLandingPads; -impl<'tcx> MirPass<'tcx> for NoLandingPads<'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) } @@ -24,15 +16,11 @@ impl<'tcx> MirPass<'tcx> for NoLandingPads<'tcx> { pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if tcx.sess.no_landing_pads() { - NoLandingPads::new(tcx).visit_body(body); + NoLandingPads.visit_body(body); } } -impl<'tcx> MutVisitor<'tcx> for NoLandingPads<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - +impl<'tcx> MutVisitor<'tcx> for NoLandingPads { fn visit_terminator_kind(&mut self, kind: &mut TerminatorKind<'tcx>, location: Location) { diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 7a9c489fa791e..7d1b96b8be170 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -17,10 +17,10 @@ use rustc::mir::*; use rustc::mir::visit::{PlaceContext, MutatingUseContext, MutVisitor, Visitor}; use rustc::mir::traversal::ReversePostorder; use rustc::ty::subst::InternalSubsts; -use rustc::ty::{List, TyCtxt}; +use rustc::ty::TyCtxt; use syntax_pos::Span; -use rustc_index::vec::{IndexVec, Idx}; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use std::{iter, mem, usize}; @@ -191,10 +191,6 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { }); } - fn is_temp_kind(&self, local: Local) -> bool { - self.source.local_kind(local) == LocalKind::Temp - } - /// Copies the initialization of this temp to the /// promoted MIR, recursing through temps. fn promote_temp(&mut self, temp: Local) -> Local { @@ -321,7 +317,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { ty, def_id, }), - projection: List::empty(), + projection: box [], } }; let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut(); @@ -339,7 +335,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { &mut place.base, promoted_place(ty, span).base, ), - projection: List::empty(), + projection: box [], }) } _ => bug!() @@ -396,30 +392,14 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { /// Replaces all temporaries with their promoted counterparts. impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) { - if self.is_temp_kind(*local) { + if self.source.local_kind(*local) == LocalKind::Temp { *local = self.promote_temp(*local); } } - - fn process_projection_elem( - &mut self, - elem: &PlaceElem<'tcx>, - ) -> Option> { - match elem { - PlaceElem::Index(local) if self.is_temp_kind(*local) => { - Some(PlaceElem::Index(self.promote_temp(*local))) - } - _ => None, - } - } } pub fn promote_candidates<'tcx>( @@ -438,13 +418,14 @@ pub fn promote_candidates<'tcx>( match candidate { Candidate::Repeat(Location { block, statement_index }) | Candidate::Ref(Location { block, statement_index }) => { - match &body[block].statements[statement_index].kind { - StatementKind::Assign(box(place, _)) => { - if let Some(local) = place.as_local() { - if temps[local] == TempState::PromotedOut { - // Already promoted. - continue; - } + match body[block].statements[statement_index].kind { + StatementKind::Assign(box(Place { + base: PlaceBase::Local(local), + projection: box [], + }, _)) => { + if temps[local] == TempState::PromotedOut { + // Already promoted. + continue; } } _ => {} @@ -490,30 +471,28 @@ pub fn promote_candidates<'tcx>( let promoted = |index: Local| temps[index] == TempState::PromotedOut; for block in body.basic_blocks_mut() { block.statements.retain(|statement| { - match &statement.kind { - StatementKind::Assign(box(place, _)) => { - if let Some(index) = place.as_local() { - !promoted(index) - } else { - true - } - } + match statement.kind { + StatementKind::Assign(box(Place { + base: PlaceBase::Local(index), + projection: box [], + }, _)) | StatementKind::StorageLive(index) | StatementKind::StorageDead(index) => { - !promoted(*index) + !promoted(index) } _ => true } }); let terminator = block.terminator_mut(); - match &terminator.kind { - TerminatorKind::Drop { location: place, target, .. } => { - if let Some(index) = place.as_local() { - if promoted(index) { - terminator.kind = TerminatorKind::Goto { - target: *target, - }; - } + match terminator.kind { + TerminatorKind::Drop { location: Place { + base: PlaceBase::Local(index), + projection: box [], + }, target, .. } => { + if promoted(index) { + terminator.kind = TerminatorKind::Goto { + target, + }; } } _ => {} diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 6aba91f416299..387540655f07b 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -4,8 +4,8 @@ //! The Qualif flags below can be used to also provide better //! diagnostics as to why a constant rvalue wasn't promoted. -use rustc_index::bit_set::BitSet; -use rustc_index::vec::IndexVec; +use rustc_data_structures::bit_set::BitSet; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::FxHashSet; use rustc_target::spec::abi::Abi; use rustc::hir; @@ -292,8 +292,8 @@ trait Qualif { Rvalue::Ref(_, _, ref place) => { // Special-case reborrows to be more like a copy of the reference. - if let &[ref proj_base @ .., elem] = place.projection.as_ref() { - if ProjectionElem::Deref == elem { + 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.kind { return Self::in_place(cx, PlaceRef { @@ -1024,12 +1024,23 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { new_errors.dedup(); if self.errors != new_errors { - validator_mismatch( - self.tcx, - body, - std::mem::replace(&mut self.errors, vec![]), - new_errors, - ); + error!("old validator: {:?}", self.errors); + error!("new validator: {:?}", new_errors); + + // ICE on nightly if the validators do not emit exactly the same errors. + // Users can supress this panic with an unstable compiler flag (hopefully after + // filing an issue). + let opts = &self.tcx.sess.opts; + let trigger_ice = opts.unstable_features.is_nightly_build() + && !opts.debugging_opts.suppress_const_validation_back_compat_ice; + + if trigger_ice { + span_bug!( + body.span, + "{}", + VALIDATOR_MISMATCH_ERR, + ); + } } } @@ -1041,24 +1052,26 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { match *candidate { Candidate::Repeat(Location { block: bb, statement_index: stmt_idx }) => { if let StatementKind::Assign(box(_, Rvalue::Repeat( - Operand::Move(place), + Operand::Move(Place { + base: PlaceBase::Local(index), + projection: box [], + }), _ - ))) = &self.body[bb].statements[stmt_idx].kind { - if let Some(index) = place.as_local() { - promoted_temps.insert(index); - } + ))) = 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) + Rvalue::Ref(_, _, Place { + base: PlaceBase::Local(index), + projection: box [], + }) ) - ) = &self.body[bb].statements[stmt_idx].kind { - if let Some(index) = place.as_local() { - promoted_temps.insert(index); - } + ) = self.body[bb].statements[stmt_idx].kind { + promoted_temps.insert(index); } } Candidate::Argument { .. } => {} @@ -1143,87 +1156,82 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { } } - fn visit_projection_elem( + fn visit_projection( &mut self, place_base: &PlaceBase<'tcx>, - proj_base: &[PlaceElem<'tcx>], - elem: &PlaceElem<'tcx>, + proj: &[PlaceElem<'tcx>], context: PlaceContext, location: Location, ) { debug!( - "visit_projection_elem: place_base={:?} proj_base={:?} elem={:?} \ - context={:?} location={:?}", - place_base, - proj_base, - elem, - context, - location, + "visit_place_projection: proj={:?} context={:?} location={:?}", + proj, context, location, ); + self.super_projection(place_base, proj, context, location); - self.super_projection_elem(place_base, proj_base, elem, context, location); - - match elem { - ProjectionElem::Deref => { - if context.is_mutating_use() { - // `not_const` errors out in const contexts - self.not_const(ops::MutDeref) - } - let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty; - match self.mode { - Mode::NonConstFn => {} - _ if self.suppress_errors => {} - _ => { - if let ty::RawPtr(_) = base_ty.kind { - if !self.tcx.features().const_raw_ptr_deref { - self.record_error(ops::RawPtrDeref); - 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, - ), - ); - } - } + 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(ops::MutDeref) } - } - } - - 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 - && !self.suppress_errors - { - self.record_error(ops::UnionAccess); + let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty; + match self.mode { + Mode::NonConstFn => {} + _ if self.suppress_errors => {} + _ => { + if let ty::RawPtr(_) = base_ty.kind { + if !self.tcx.features().const_raw_ptr_deref { + self.record_error(ops::RawPtrDeref); 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, + ), ); } - }, + } + } + } + } + + 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 + && !self.suppress_errors + { + self.record_error(ops::UnionAccess); + 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 - => {}, + | Mode::NonConstFn + | Mode::Static + | Mode::StaticMut + | Mode::Const + => {}, + } } } } - } - ProjectionElem::Downcast(..) => { - self.not_const(ops::Downcast) + ProjectionElem::Downcast(..) => { + self.not_const(ops::Downcast) + } } } } @@ -1235,7 +1243,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { match *operand { Operand::Move(ref place) => { // Mark the consumed locals to indicate later drops are noops. - if let Some(local) = place.as_local() { + if let Place { + base: PlaceBase::Local(local), + projection: box [], + } = *place { self.cx.per_local[NeedsDrop].remove(local); } } @@ -1251,8 +1262,8 @@ 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 &[ref proj_base @ .., elem] = place.projection.as_ref() { - if elem == ProjectionElem::Deref { + 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.kind { reborrow_place = Some(proj_base); @@ -1563,7 +1574,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { unleash_miri!(self); // HACK(eddyb): emulate a bit of dataflow analysis, // conservatively, that drop elaboration will do. - let needs_drop = if let Some(local) = place.as_local() { + let needs_drop = if let Place { + base: PlaceBase::Local(local), + projection: box [], + } = *place { if NeedsDrop::in_local(self, local) { Some(self.body.local_decls[local].source_info.span) } else { @@ -1809,17 +1823,16 @@ fn remove_drop_and_storage_dead_on_promoted_locals( } }); let terminator = block.terminator_mut(); - match &terminator.kind { + match terminator.kind { TerminatorKind::Drop { - location, + location: Place { + base: PlaceBase::Local(index), + projection: box [], + }, target, .. - } => { - if let Some(index) = location.as_local() { - if promoted_temps.contains(index) { - terminator.kind = TerminatorKind::Goto { target: *target }; - } - } + } if promoted_temps.contains(index) => { + terminator.kind = TerminatorKind::Goto { target }; } _ => {} } @@ -1852,58 +1865,6 @@ fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option, - body: &Body<'tcx>, - mut old_errors: Vec<(Span, String)>, - mut new_errors: Vec<(Span, String)>, -) { - error!("old validator: {:?}", old_errors); - error!("new validator: {:?}", new_errors); - - // ICE on nightly if the validators do not emit exactly the same errors. - // Users can supress this panic with an unstable compiler flag (hopefully after - // filing an issue). - let opts = &tcx.sess.opts; - let strict_validation_enabled = opts.unstable_features.is_nightly_build() - && !opts.debugging_opts.suppress_const_validation_back_compat_ice; - - if !strict_validation_enabled { - return; - } - - // If this difference would cause a regression from the old to the new or vice versa, trigger - // the ICE. - if old_errors.is_empty() || new_errors.is_empty() { - span_bug!(body.span, "{}", VALIDATOR_MISMATCH_ERR); - } - - // HACK: Borrows that would allow mutation are forbidden in const contexts, but they cause the - // new validator to be more conservative about when a dropped local has been moved out of. - // - // Supress the mismatch ICE in cases where the validators disagree only on the number of - // `LiveDrop` errors and both observe the same sequence of `MutBorrow`s. - - let is_live_drop = |(_, s): &mut (_, String)| s.starts_with("LiveDrop"); - let is_mut_borrow = |(_, s): &&(_, String)| s.starts_with("MutBorrow"); - - let old_live_drops: Vec<_> = old_errors.drain_filter(is_live_drop).collect(); - let new_live_drops: Vec<_> = new_errors.drain_filter(is_live_drop).collect(); - - let only_live_drops_differ = old_live_drops != new_live_drops && old_errors == new_errors; - - let old_mut_borrows = old_errors.iter().filter(is_mut_borrow); - let new_mut_borrows = new_errors.iter().filter(is_mut_borrow); - - let at_least_one_mut_borrow = old_mut_borrows.clone().next().is_some(); - - if only_live_drops_differ && at_least_one_mut_borrow && old_mut_borrows.eq(new_mut_borrows) { - return; - } - - span_bug!(body.span, "{}", VALIDATOR_MISMATCH_ERR); -} - const VALIDATOR_MISMATCH_ERR: &str = r"Disagreement between legacy and dataflow-based const validators. After filing an issue, use `-Zsuppress-const-validation-back-compat-ice` to compile your code."; diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index c4e44091bc90d..cf0ee1bf09222 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -14,7 +14,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) - let mut current = def_id; loop { let predicates = tcx.predicates_of(current); - for (predicate, _) in predicates.predicates { + for (predicate, _) in &predicates.predicates { match predicate { | Predicate::RegionOutlives(_) | Predicate::TypeOutlives(_) @@ -259,8 +259,8 @@ fn check_place( def_id: DefId, body: &Body<'tcx> ) -> McfResult { - let mut cursor = place.projection.as_ref(); - while let &[ref proj_base @ .., elem] = cursor { + let mut cursor = &*place.projection; + while let [proj_base @ .., elem] = cursor { cursor = proj_base; match elem { ProjectionElem::Downcast(..) => { diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index 130393e2c4c86..70b11944e2fbc 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -1,6 +1,6 @@ use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::bit_set::BitSet; use crate::transform::{MirPass, MirSource}; use crate::util::patch::MirPatch; @@ -32,7 +32,7 @@ impl RemoveNoopLandingPads { nop_landing_pads: &BitSet, ) -> bool { for stmt in &body[bb].statements { - match &stmt.kind { + match stmt.kind { StatementKind::FakeRead(..) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | @@ -41,13 +41,12 @@ impl RemoveNoopLandingPads { // These are all nops in a landing pad } - StatementKind::Assign(box(place, Rvalue::Use(_))) => { - if place.as_local().is_some() { - // Writing to a local (e.g., a drop flag) does not - // turn a landing pad to a non-nop - } else { - return false; - } + StatementKind::Assign(box(Place { + base: PlaceBase::Local(_), + projection: box [], + }, Rvalue::Use(_))) => { + // Writing to a local (e.g., a drop flag) does not + // turn a landing pad to a non-nop } StatementKind::Assign { .. } | diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index aada7641df67a..539645d0227f4 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -3,21 +3,19 @@ use syntax::ast; use syntax::symbol::sym; use syntax_pos::Span; -use rustc::ty::{self, TyCtxt, Ty}; +use rustc::ty::{self, TyCtxt}; use rustc::hir::def_id::DefId; -use rustc::mir::{self, Body, Location, Local}; -use rustc_index::bit_set::BitSet; +use rustc::mir::{self, Body, Location}; +use rustc_data_structures::bit_set::BitSet; use crate::transform::{MirPass, MirSource}; use crate::dataflow::{do_dataflow, DebugFormatted}; use crate::dataflow::MoveDataParamEnv; use crate::dataflow::BitDenotation; use crate::dataflow::DataflowResults; -use crate::dataflow::DataflowResultsCursor; use crate::dataflow::{ DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces }; -use crate::dataflow::IndirectlyMutableLocals; use crate::dataflow::move_paths::{MovePathIndex, LookupResult}; use crate::dataflow::move_paths::{HasMoveData, MoveData}; @@ -52,10 +50,6 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds, DefinitelyInitializedPlaces::new(tcx, body, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); - let flow_indirectly_mut = - do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds, - IndirectlyMutableLocals::new(tcx, body, param_env), - |_, i| DebugFormatted::new(&i)); if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_init).is_some() { sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_inits); @@ -66,9 +60,6 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { if has_rustc_mir_with(&attributes, sym::rustc_peek_definite_init).is_some() { sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_def_inits); } - if has_rustc_mir_with(&attributes, sym::rustc_peek_indirectly_mutable).is_some() { - sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_indirectly_mut); - } if has_rustc_mir_with(&attributes, sym::stop_after_dataflow).is_some() { tcx.sess.fatal("stop_after_dataflow ended compilation"); } @@ -97,204 +88,151 @@ pub fn sanity_check_via_rustc_peek<'tcx, O>( def_id: DefId, _attributes: &[ast::Attribute], results: &DataflowResults<'tcx, O>, -) where O: RustcPeekAt<'tcx> { +) where + O: BitDenotation<'tcx, Idx = MovePathIndex> + HasMoveData<'tcx>, +{ debug!("sanity_check_via_rustc_peek def_id: {:?}", def_id); + // FIXME: this is not DRY. Figure out way to abstract this and + // `dataflow::build_sets`. (But note it is doing non-standard + // stuff, so such generalization may not be realistic.) - let mut cursor = DataflowResultsCursor::new(results, body); - - let peek_calls = body - .basic_blocks() - .iter_enumerated() - .filter_map(|(bb, block_data)| { - PeekCall::from_terminator(tcx, block_data.terminator()) - .map(|call| (bb, block_data, call)) - }); - - for (bb, block_data, call) in peek_calls { - // Look for a sequence like the following to indicate that we should be peeking at `_1`: - // _2 = &_1; - // rustc_peek(_2); - // - // /* or */ - // - // _2 = _1; - // rustc_peek(_2); - let (statement_index, peek_rval) = block_data - .statements - .iter() - .enumerate() - .filter_map(|(i, stmt)| value_assigned_to_local(stmt, call.arg).map(|rval| (i, rval))) - .next() - .expect("call to rustc_peek should be preceded by \ - assignment to temporary holding its argument"); - - match (call.kind, peek_rval) { - | (PeekCallKind::ByRef, mir::Rvalue::Ref(_, _, place)) - | (PeekCallKind::ByVal, mir::Rvalue::Use(mir::Operand::Move(place))) - | (PeekCallKind::ByVal, mir::Rvalue::Use(mir::Operand::Copy(place))) - => { - let loc = Location { block: bb, statement_index }; - cursor.seek(loc); - let state = cursor.get(); - results.operator().peek_at(tcx, place, state, call); - } - - _ => { - let msg = "rustc_peek: argument expression \ - must be either `place` or `&place`"; - tcx.sess.span_err(call.span, msg); - } - } - } -} - -/// If `stmt` is an assignment where the LHS is the given local (with no projections), returns the -/// RHS of the assignment. -fn value_assigned_to_local<'a, 'tcx>( - stmt: &'a mir::Statement<'tcx>, - local: Local, -) -> Option<&'a mir::Rvalue<'tcx>> { - if let mir::StatementKind::Assign(box (place, rvalue)) = &stmt.kind { - if let Some(l) = place.as_local() { - if local == l { - return Some(&*rvalue); - } - } + for bb in body.basic_blocks().indices() { + each_block(tcx, body, results, bb); } - - None } -#[derive(Clone, Copy, Debug)] -enum PeekCallKind { - ByVal, - ByRef, -} - -impl PeekCallKind { - fn from_arg_ty(arg: Ty<'_>) -> Self { - match arg.kind { - ty::Ref(_, _, _) => PeekCallKind::ByRef, - _ => PeekCallKind::ByVal, +fn each_block<'tcx, O>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + results: &DataflowResults<'tcx, O>, + bb: mir::BasicBlock, +) where + O: BitDenotation<'tcx, Idx = MovePathIndex> + HasMoveData<'tcx>, +{ + let move_data = results.0.operator.move_data(); + let mir::BasicBlockData { ref statements, ref terminator, is_cleanup: _ } = body[bb]; + + let (args, span) = match is_rustc_peek(tcx, terminator) { + Some(args_and_span) => args_and_span, + None => return, + }; + assert!(args.len() == 1); + let peek_arg_place = match args[0] { + mir::Operand::Copy(ref place @ mir::Place { + base: mir::PlaceBase::Local(_), + projection: box [], + }) | + mir::Operand::Move(ref place @ mir::Place { + base: mir::PlaceBase::Local(_), + projection: box [], + }) => Some(place), + _ => None, + }; + + let peek_arg_place = match peek_arg_place { + Some(arg) => arg, + None => { + tcx.sess.diagnostic().span_err( + span, "dataflow::sanity_check cannot feed a non-temp to rustc_peek."); + return; } - } -} - -#[derive(Clone, Copy, Debug)] -pub struct PeekCall { - arg: Local, - kind: PeekCallKind, - span: Span, -} - -impl PeekCall { - fn from_terminator<'tcx>( - tcx: TyCtxt<'tcx>, - terminator: &mir::Terminator<'tcx>, - ) -> Option { - use mir::Operand; - - let span = terminator.source_info.span; - if let mir::TerminatorKind::Call { func: Operand::Constant(func), args, .. } = - &terminator.kind - { - if let ty::FnDef(def_id, substs) = func.literal.ty.kind { - let sig = tcx.fn_sig(def_id); - let name = tcx.item_name(def_id); - if sig.abi() != Abi::RustIntrinsic || name != sym::rustc_peek { - return None; - } + }; + + let mut on_entry = results.0.sets.entry_set_for(bb.index()).to_owned(); + let mut trans = results.0.sets.trans_for(bb.index()).clone(); + + // Emulate effect of all statements in the block up to (but not + // including) the borrow within `peek_arg_place`. Do *not* include + // call to `peek_arg_place` itself (since we are peeking the state + // of the argument at time immediate preceding Call to + // `rustc_peek`). + + for (j, stmt) in statements.iter().enumerate() { + debug!("rustc_peek: ({:?},{}) {:?}", bb, j, stmt); + let (place, rvalue) = match stmt.kind { + mir::StatementKind::Assign(box(ref place, ref rvalue)) => { + (place, rvalue) + } + mir::StatementKind::FakeRead(..) | + mir::StatementKind::StorageLive(_) | + mir::StatementKind::StorageDead(_) | + mir::StatementKind::InlineAsm { .. } | + mir::StatementKind::Retag { .. } | + mir::StatementKind::AscribeUserType(..) | + mir::StatementKind::Nop => continue, + mir::StatementKind::SetDiscriminant{ .. } => + span_bug!(stmt.source_info.span, + "sanity_check should run before Deaggregator inserts SetDiscriminant"), + }; - assert_eq!(args.len(), 1); - let kind = PeekCallKind::from_arg_ty(substs.type_at(0)); - let arg = match &args[0] { - Operand::Copy(place) | Operand::Move(place) => { - if let Some(local) = place.as_local() { - local - } else { - tcx.sess.diagnostic().span_err( - span, - "dataflow::sanity_check cannot feed a non-temp to rustc_peek.", - ); - return None; + if place == peek_arg_place { + 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) => { + let bit_state = on_entry.contains(peek_mpi); + debug!("rustc_peek({:?} = &{:?}) bit_state: {}", + place, peeking_at_place, bit_state); + if !bit_state { + tcx.sess.span_err(span, "rustc_peek: bit not set"); } } - _ => { - tcx.sess.diagnostic().span_err( - span, - "dataflow::sanity_check cannot feed a non-temp to rustc_peek.", - ); - return None; + LookupResult::Parent(..) => { + tcx.sess.span_err(span, "rustc_peek: argument untracked"); } - }; - - return Some(PeekCall { - arg, - kind, - span, - }); + } + return; + } else { + // Our search should have been over, but the input + // does not match expectations of `rustc_peek` for + // this sanity_check. + let msg = "rustc_peek: argument expression \ + must be immediate borrow of form `&expr`"; + tcx.sess.span_err(span, msg); } } - None + let lhs_mpi = move_data.rev_lookup.find(place.as_ref()); + + debug!("rustc_peek: computing effect on place: {:?} ({:?}) in stmt: {:?}", + place, lhs_mpi, stmt); + // reset GEN and KILL sets before emulating their effect. + trans.clear(); + results.0.operator.before_statement_effect( + &mut trans, + Location { block: bb, statement_index: j }); + results.0.operator.statement_effect( + &mut trans, + Location { block: bb, statement_index: j }); + trans.apply(&mut on_entry); } -} -pub trait RustcPeekAt<'tcx>: BitDenotation<'tcx> { - fn peek_at( - &self, - tcx: TyCtxt<'tcx>, - place: &mir::Place<'tcx>, - flow_state: &BitSet, - call: PeekCall, - ); + results.0.operator.before_terminator_effect( + &mut trans, + Location { block: bb, statement_index: statements.len() }); + + tcx.sess.span_err(span, &format!("rustc_peek: MIR did not match \ + anticipated pattern; note that \ + rustc_peek expects input of \ + form `&expr`")); } -impl<'tcx, O> RustcPeekAt<'tcx> for O - where O: BitDenotation<'tcx, Idx = MovePathIndex> + HasMoveData<'tcx>, -{ - fn peek_at( - &self, - tcx: TyCtxt<'tcx>, - place: &mir::Place<'tcx>, - flow_state: &BitSet, - call: PeekCall, - ) { - match self.move_data().rev_lookup.find(place.as_ref()) { - LookupResult::Exact(peek_mpi) => { - let bit_state = flow_state.contains(peek_mpi); - debug!("rustc_peek({:?} = &{:?}) bit_state: {}", - call.arg, place, bit_state); - if !bit_state { - tcx.sess.span_err(call.span, "rustc_peek: bit not set"); +fn is_rustc_peek<'a, 'tcx>( + tcx: TyCtxt<'tcx>, + terminator: &'a Option>, +) -> Option<(&'a [mir::Operand<'tcx>], Span)> { + 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.literal.ty.kind { + let abi = tcx.fn_sig(def_id).abi(); + let name = tcx.item_name(def_id); + if abi == Abi::RustIntrinsic && name == sym::rustc_peek { + return Some((args, source_info.span)); + } } } - - LookupResult::Parent(..) => { - tcx.sess.span_err(call.span, "rustc_peek: argument untracked"); - } - } - } -} - -impl<'tcx> RustcPeekAt<'tcx> for IndirectlyMutableLocals<'_, 'tcx> { - fn peek_at( - &self, - tcx: TyCtxt<'tcx>, - place: &mir::Place<'tcx>, - flow_state: &BitSet, - call: PeekCall, - ) { - warn!("peek_at: place={:?}", place); - let local = if let Some(l) = place.as_local() { - l - } else { - tcx.sess.span_err(call.span, "rustc_peek: argument was not a local"); - return; - }; - - if !flow_state.contains(local) { - tcx.sess.span_err(call.span, "rustc_peek: bit not set"); } } + return None; } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 1b90ea78c6450..d4599ee08aa46 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -27,11 +27,11 @@ //! naively generate still contains the `_a = ()` write in the unreachable block "after" the //! return. -use rustc_index::bit_set::BitSet; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::bit_set::BitSet; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext, MutatingUseContext}; +use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext}; use rustc::session::config::DebugInfo; use std::borrow::Cow; use crate::transform::{MirPass, MirSource}; @@ -293,33 +293,25 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { pub struct SimplifyLocals; impl<'tcx> MirPass<'tcx> for SimplifyLocals { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { - trace!("running SimplifyLocals on {:?}", source); - let locals = { - let mut marker = DeclMarker { - locals: BitSet::new_empty(body.local_decls.len()), - body, - }; - marker.visit_body(body); - // Return pointer and arguments are always live - marker.locals.insert(RETURN_PLACE); - for arg in body.args_iter() { - marker.locals.insert(arg); - } + 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 + marker.locals.insert(RETURN_PLACE); + for arg in body.args_iter() { + marker.locals.insert(arg); + } - // We may need to keep dead user variables live for debuginfo. - if tcx.sess.opts.debuginfo == DebugInfo::Full { - for local in body.vars_iter() { - marker.locals.insert(local); - } + // We may need to keep dead user variables live for debuginfo. + if tcx.sess.opts.debuginfo == DebugInfo::Full { + for local in body.vars_iter() { + marker.locals.insert(local); } + } - marker.locals - }; - - let map = make_local_map(&mut body.local_decls, locals); + let map = make_local_map(&mut body.local_decls, marker.locals); // Update references to all vars and tmps now - LocalUpdater { map, tcx }.visit_body(body); + LocalUpdater { map }.visit_body(body); body.local_decls.shrink_to_fit(); } } @@ -342,81 +334,39 @@ fn make_local_map( map } -struct DeclMarker<'a, 'tcx> { +struct DeclMarker { pub locals: BitSet, - pub body: &'a Body<'tcx>, } -impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> { - fn visit_local(&mut self, local: &Local, ctx: PlaceContext, location: Location) { +impl<'tcx> Visitor<'tcx> for DeclMarker { + fn visit_local(&mut self, local: &Local, ctx: PlaceContext, _: Location) { // Ignore storage markers altogether, they get removed along with their otherwise unused // decls. // FIXME: Extend this to all non-uses. - if ctx.is_storage_marker() { - return; - } - - // Ignore stores of constants because `ConstProp` and `CopyProp` can remove uses of many - // of these locals. However, if the local is still needed, then it will be referenced in - // another place and we'll mark it as being used there. - if ctx == PlaceContext::MutatingUse(MutatingUseContext::Store) { - let stmt = - &self.body.basic_blocks()[location.block].statements[location.statement_index]; - if let StatementKind::Assign(box (p, Rvalue::Use(Operand::Constant(c)))) = &stmt.kind { - if p.as_local().is_some() { - trace!("skipping store of const value {:?} to {:?}", c, local); - return; - } - } + if !ctx.is_storage_marker() { + self.locals.insert(*local); } - - self.locals.insert(*local); } } -struct LocalUpdater<'tcx> { +struct LocalUpdater { map: IndexVec>, - tcx: TyCtxt<'tcx>, } -impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - +impl<'tcx> MutVisitor<'tcx> for LocalUpdater { fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) { // Remove unnecessary StorageLive and StorageDead annotations. data.statements.retain(|stmt| { - match &stmt.kind { + match stmt.kind { StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => { - self.map[*l].is_some() - } - StatementKind::Assign(box (place, _)) => { - if let Some(local) = place.as_local() { - self.map[local].is_some() - } else { - true - } + self.map[l].is_some() } _ => true } }); self.super_basic_block_data(block, data); } - fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) { *l = self.map[*l].unwrap(); } - - fn process_projection_elem( - &mut self, - elem: &PlaceElem<'tcx>, - ) -> Option> { - match elem { - PlaceElem::Index(local) => { - Some(PlaceElem::Index(self.map[*local].unwrap())) - } - _ => None - } - } } diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index e4c2f7d389b50..eb61cd2f657a2 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -30,7 +30,7 @@ use rustc::ty; use rustc::ty::TyCtxt; use rustc::mir::*; use rustc::mir::visit::{Visitor, PlaceContext, NonUseContext}; -use rustc_index::vec::{IndexVec}; +use rustc_data_structures::indexed_vec::{IndexVec}; use crate::transform::{MirPass, MirSource}; use crate::util::patch::MirPatch; @@ -61,7 +61,7 @@ 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 &[ref proj_base @ .., elem] = src_place.projection.as_ref() { + if let box [proj_base @ .., elem] = &src_place.projection { if let ProjectionElem::ConstantIndex{offset: _, min_length: _, from_end: false} = elem { @@ -116,13 +116,16 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> { min_length: size, from_end: false, }); - self.patch.add_assign( - location, - Place::from(temp), - Rvalue::Use(Operand::Move(Place { - base: base.clone(), - projection: self.tcx.intern_place_elems(&projection), - })), + self.patch.add_assign(location, + Place::from(temp), + Rvalue::Use( + Operand::Move( + Place { + base: base.clone(), + projection: projection.into_boxed_slice(), + } + ) + ) ); temp }).collect(); @@ -150,13 +153,16 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> { min_length: size, from_end: false, }); - self.patch.add_assign( - location, - dst_place.clone(), - Rvalue::Use(Operand::Move(Place { - base: base.clone(), - projection: self.tcx.intern_place_elems(&projection), - })), + self.patch.add_assign(location, + dst_place.clone(), + Rvalue::Use( + Operand::Move( + Place { + base: base.clone(), + projection: projection.into_boxed_slice(), + } + ) + ) ); } _ => {} @@ -179,11 +185,9 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> { // // replaced by _10 = move _2[:-1]; -pub struct RestoreSubsliceArrayMoveOut<'tcx> { - tcx: TyCtxt<'tcx> -} +pub struct RestoreSubsliceArrayMoveOut; -impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'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()); @@ -199,17 +203,18 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { 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) = item { - if let Some(local) = place.as_local() { - let local_use = &visitor.locals_use[local]; - let opt_index_and_place = - Self::try_get_item_source(local_use, body); - // each local should be used twice: - // in assign and in aggregate statements - if local_use.use_count == 2 && opt_index_and_place.is_some() { - let (index, src_place) = opt_index_and_place.unwrap(); - return Some((local_use, index, src_place)); - } + if let Operand::Move(Place { + base: PlaceBase::Local(local), + projection: box [], + }) = item { + let local_use = &visitor.locals_use[*local]; + let opt_index_and_place = + Self::try_get_item_source(local_use, body); + // each local should be used twice: + // in assign and in aggregate statements + if local_use.use_count == 2 && opt_index_and_place.is_some() { + let (index, src_place) = opt_index_and_place.unwrap(); + return Some((local_use, index, src_place)); } } None @@ -225,9 +230,7 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { None } }); - let restore_subslice = RestoreSubsliceArrayMoveOut { tcx }; - restore_subslice - .check_and_patch(*candidate, &items, opt_size, &mut patch, dst_place); + Self::check_and_patch(*candidate, &items, opt_size, &mut patch, dst_place); } } } @@ -236,20 +239,15 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { } } -impl RestoreSubsliceArrayMoveOut<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> Self { - RestoreSubsliceArrayMoveOut { tcx } - } - +impl RestoreSubsliceArrayMoveOut { // Checks that source has size, all locals are inited from same source place and // indices is an integer interval. If all checks pass do the replacent. // items are Vec> - fn check_and_patch(&self, - candidate: Location, - items: &[Option<(&LocalUse, u32, PlaceRef<'_, 'tcx>)>], - opt_size: Option, - patch: &mut MirPatch<'tcx>, - dst_place: &Place<'tcx>) { + fn check_and_patch<'tcx>(candidate: Location, + items: &[Option<(&LocalUse, u32, PlaceRef<'_, 'tcx>)>], + opt_size: Option, + patch: &mut MirPatch<'tcx>, + dst_place: &Place<'tcx>) { let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2); if opt_size.is_some() && items.iter().all( @@ -282,40 +280,46 @@ impl RestoreSubsliceArrayMoveOut<'tcx> { dst_place.clone(), Rvalue::Use(Operand::Move(Place { base: src_place.base.clone(), - projection: self.tcx.intern_place_elems(&projection), + projection: projection.into_boxed_slice(), })), ); } } - fn try_get_item_source<'a>(local_use: &LocalUse, - body: &'a Body<'tcx>) -> Option<(u32, PlaceRef<'a, 'tcx>)> { + fn try_get_item_source<'a, 'tcx>(local_use: &LocalUse, + body: &'a Body<'tcx>) -> Option<(u32, PlaceRef<'a, 'tcx>)> { if let Some(location) = local_use.first_use { let block = &body[location.block]; if block.statements.len() > location.statement_index { let statement = &block.statements[location.statement_index]; if let StatementKind::Assign( - box(place, Rvalue::Use(Operand::Move(src_place))) + 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 { - if let (Some(_), PlaceRef { - base: _, - projection: &[.., ProjectionElem::ConstantIndex { - offset, min_length: _, from_end: false - }], - }) = (place.as_local(), src_place.as_ref()) { - if let StatementKind::Assign( - box(_, Rvalue::Use(Operand::Move(place))) - ) = &statement.kind { - if let PlaceRef { + // FIXME remove once we can use slices patterns + if let StatementKind::Assign( + box( + _, + Rvalue::Use(Operand::Move(Place { base, - projection: &[ref proj_base @ .., _], - } = place.as_ref() { - return Some((offset, PlaceRef { - base, - projection: proj_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 e6c3e4384d7ae..b3565d40b8e21 100644 --- a/src/librustc_mir/util/aggregate.rs +++ b/src/librustc_mir/util/aggregate.rs @@ -1,7 +1,7 @@ use rustc::mir::*; -use rustc::ty::{Ty, TyCtxt}; +use rustc::ty::Ty; use rustc::ty::layout::VariantIdx; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use std::iter::TrustedLen; @@ -17,7 +17,6 @@ pub fn expand_aggregate<'tcx>( operands: impl Iterator, Ty<'tcx>)> + TrustedLen, kind: AggregateKind<'tcx>, source_info: SourceInfo, - tcx: TyCtxt<'tcx>, ) -> impl Iterator> + TrustedLen { let mut set_discriminant = None; let active_field_index = match kind { @@ -30,7 +29,7 @@ pub fn expand_aggregate<'tcx>( }, source_info, }); - lhs = tcx.mk_place_downcast(lhs, adt_def, variant_index); + lhs = lhs.downcast(adt_def, variant_index); } active_field_index } @@ -59,7 +58,7 @@ pub fn expand_aggregate<'tcx>( // FIXME(eddyb) `offset` should be u64. let offset = i as u32; assert_eq!(offset as usize, i); - tcx.mk_place_elem(lhs.clone(), ProjectionElem::ConstantIndex { + lhs.clone().elem(ProjectionElem::ConstantIndex { offset, // FIXME(eddyb) `min_length` doesn't appear to be used. min_length: offset + 1, @@ -67,7 +66,7 @@ pub fn expand_aggregate<'tcx>( }) } else { let field = Field::new(active_field_index.unwrap_or(i)); - tcx.mk_place_field(lhs.clone(), field, ty) + lhs.clone().field(field, ty) }; Statement { source_info, diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs index f949fcf0745f0..1bad85ec42d08 100644 --- a/src/librustc_mir/util/alignment.rs +++ b/src/librustc_mir/util/alignment.rs @@ -38,8 +38,8 @@ fn is_within_packed<'tcx, L>(tcx: TyCtxt<'tcx>, local_decls: &L, place: &Place<' where L: HasLocalDecls<'tcx>, { - let mut cursor = place.projection.as_ref(); - while let &[ref proj_base @ .., elem] = cursor { + let mut cursor = &*place.projection; + while let [proj_base @ .., elem] = cursor { cursor = proj_base; match elem { diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 725ec84ca6237..59821440c6619 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -1,9 +1,8 @@ //! Def-use analysis. -use rustc::mir::{Body, Local, Location, PlaceElem}; +use rustc::mir::{Local, Location, Body}; use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor}; -use rustc::ty::TyCtxt; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use std::mem; pub struct DefUseAnalysis { @@ -48,26 +47,23 @@ impl DefUseAnalysis { &self.info[local] } - fn mutate_defs_and_uses( - &self, - local: Local, - body: &mut Body<'tcx>, - new_local: Local, - tcx: TyCtxt<'tcx>, - ) { + fn mutate_defs_and_uses(&self, local: Local, body: &mut Body<'_>, mut callback: F) + where F: for<'a> FnMut(&'a mut Local, + PlaceContext, + Location) { for place_use in &self.info[local].defs_and_uses { - MutateUseVisitor::new(local, new_local, body, tcx) - .visit_location(body, place_use.location) + MutateUseVisitor::new(local, + &mut callback, + body).visit_location(body, place_use.location) } } // FIXME(pcwalton): this should update the def-use chains. pub fn replace_all_defs_and_uses_with(&self, local: Local, - body: &mut Body<'tcx>, - new_local: Local, - tcx: TyCtxt<'tcx>) { - self.mutate_defs_and_uses(local, body, new_local, tcx) + body: &mut Body<'_>, + new_local: Local) { + self.mutate_defs_and_uses(local, body, |local, _, _| *local = new_local) } } @@ -121,46 +117,30 @@ impl Info { } } -struct MutateUseVisitor<'tcx> { +struct MutateUseVisitor { query: Local, - new_local: Local, - tcx: TyCtxt<'tcx>, + callback: F, } -impl MutateUseVisitor<'tcx> { - fn new( - query: Local, - new_local: Local, - _: &Body<'tcx>, - tcx: TyCtxt<'tcx>, - ) -> MutateUseVisitor<'tcx> { - MutateUseVisitor { query, new_local, tcx } +impl MutateUseVisitor { + fn new(query: Local, callback: F, _: &Body<'_>) + -> MutateUseVisitor + where F: for<'a> FnMut(&'a mut Local, PlaceContext, Location) { + MutateUseVisitor { + query, + callback, + } } } -impl MutVisitor<'tcx> for MutateUseVisitor<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - +impl MutVisitor<'_> for MutateUseVisitor + where F: for<'a> FnMut(&'a mut Local, PlaceContext, Location) { fn visit_local(&mut self, local: &mut Local, - _context: PlaceContext, - _location: Location) { + context: PlaceContext, + location: Location) { if *local == self.query { - *local = self.new_local; - } - } - - fn process_projection_elem( - &mut self, - elem: &PlaceElem<'tcx>, - ) -> Option> { - match elem { - PlaceElem::Index(local) if *local == self.query => { - Some(PlaceElem::Index(self.new_local)) - } - _ => None, + (self.callback)(local, context, location) } } } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index a1846a1fb5eaf..e1015edfa8eec 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -7,7 +7,7 @@ use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::VariantIdx; use rustc::ty::subst::SubstsRef; use rustc::ty::util::IntTypeExt; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use crate::util::patch::MirPatch; use std::convert::TryInto; @@ -200,14 +200,13 @@ where variant.fields.iter().enumerate().map(|(i, f)| { let field = Field::new(i); let subpath = self.elaborator.field_subpath(variant_path, field); - let tcx = self.tcx(); assert_eq!(self.elaborator.param_env().reveal, Reveal::All); - let field_ty = tcx.normalize_erasing_regions( + let field_ty = self.tcx().normalize_erasing_regions( self.elaborator.param_env(), - f.ty(tcx, substs), + f.ty(self.tcx(), substs), ); - (tcx.mk_place_field(base_place.clone(), field, field_ty), subpath) + (base_place.clone().field(field, field_ty), subpath) }).collect() } @@ -324,7 +323,7 @@ where debug!("open_drop_for_tuple({:?}, {:?})", self, tys); let fields = tys.iter().enumerate().map(|(i, &ty)| { - (self.tcx().mk_place_field(self.place.clone(), Field::new(i), ty), + (self.place.clone().field(Field::new(i), ty), self.elaborator.field_subpath(self.path, Field::new(i))) }).collect(); @@ -335,7 +334,7 @@ where fn open_drop_for_box(&mut self, adt: &'tcx ty::AdtDef, substs: SubstsRef<'tcx>) -> BasicBlock { debug!("open_drop_for_box({:?}, {:?}, {:?})", self, adt, substs); - let interior = self.tcx().mk_place_deref(self.place.clone()); + let interior = self.place.clone().deref(); let interior_path = self.elaborator.deref_subpath(self.path); let succ = self.succ; // FIXME(#43234) @@ -407,19 +406,14 @@ where }; let mut have_otherwise = false; - let tcx = self.tcx(); - for (variant_index, discr) in adt.discriminants(tcx) { + for (variant_index, discr) in adt.discriminants(self.tcx()) { let subpath = self.elaborator.downcast_subpath( self.path, variant_index); if let Some(variant_path) = subpath { - let base_place = tcx.mk_place_elem( - self.place.clone(), - ProjectionElem::Downcast( - Some(adt.variants[variant_index].ident.name), - variant_index, - ), - ); + let base_place = self.place.clone().elem( + ProjectionElem::Downcast(Some(adt.variants[variant_index].ident.name), + variant_index)); let fields = self.move_paths_for_fields( &base_place, variant_path, @@ -592,7 +586,7 @@ where BorrowKind::Mut { allow_two_phase_borrow: false }, Place { base: PlaceBase::Local(cur), - projection: tcx.intern_place_elems(&vec![ProjectionElem::Deref]), + projection: Box::new([ProjectionElem::Deref]), } ), Rvalue::BinaryOp(BinOp::Offset, move_(&Place::from(cur)), one)) @@ -600,7 +594,7 @@ where (Rvalue::Ref( tcx.lifetimes.re_erased, BorrowKind::Mut { allow_two_phase_borrow: false }, - tcx.mk_place_index(self.place.clone(), cur)), + self.place.clone().index(cur)), Rvalue::BinaryOp(BinOp::Add, move_(&Place::from(cur)), one)) }; @@ -633,7 +627,7 @@ where let loop_block = self.elaborator.patch().new_block(loop_block); self.elaborator.patch().patch_terminator(drop_block, TerminatorKind::Drop { - location: tcx.mk_place_deref(ptr.clone()), + location: ptr.clone().deref(), target: loop_block, unwind: unwind.into_option() }); @@ -650,27 +644,18 @@ where // ptr_based_loop // } - let tcx = self.tcx(); - if let Some(size) = opt_size { let size: u32 = size.try_into().unwrap_or_else(|_| { bug!("move out check isn't implemented for array sizes bigger than u32::MAX"); }); - let fields: Vec<(Place<'tcx>, Option)> = (0..size) - .map(|i| { - ( - tcx.mk_place_elem( - self.place.clone(), - ProjectionElem::ConstantIndex { - offset: i, - min_length: size, - from_end: false, - }, - ), - self.elaborator.array_subpath(self.path, i, size), - ) - }) - .collect(); + let fields: Vec<(Place<'tcx>, Option)> = (0..size).map(|i| { + (self.place.clone().elem(ProjectionElem::ConstantIndex{ + offset: i, + min_length: size, + from_end: false + }), + self.elaborator.array_subpath(self.path, i, size)) + }).collect(); if fields.iter().any(|(_,path)| path.is_some()) { let (succ, unwind) = self.drop_ladder_bottom(); @@ -679,6 +664,7 @@ where } let move_ = |place: &Place<'tcx>| Operand::Move(place.clone()); + let tcx = self.tcx(); let elem_size = &Place::from(self.new_temp(tcx.types.usize)); let len = &Place::from(self.new_temp(tcx.types.usize)); @@ -802,7 +788,7 @@ where let ty = self.place_ty(self.place); match ty.kind { ty::Closure(def_id, substs) => { - let tys : Vec<_> = substs.as_closure().upvar_tys(def_id, self.tcx()).collect(); + let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect(); self.open_drop_for_tuple(&tys) } // Note that `elaborate_drops` only drops the upvars of a generator, @@ -812,7 +798,7 @@ where // It effetively only contains upvars until the generator transformation runs. // See librustc_body/transform/generator.rs for more details. ty::Generator(def_id, substs, _) => { - let tys : Vec<_> = substs.as_generator().upvar_tys(def_id, self.tcx()).collect(); + let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect(); self.open_drop_for_tuple(&tys) } ty::Tuple(..) => { @@ -914,8 +900,8 @@ where ); let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| { let field = Field::new(i); - let field_ty = f.ty(tcx, substs); - Operand::Move(tcx.mk_place_field(self.place.clone(), field, field_ty)) + let field_ty = f.ty(self.tcx(), substs); + Operand::Move(self.place.clone().field(field, field_ty)) }).collect(); let call = TerminatorKind::Call { diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index 7fcb7a40a3c08..9d142d9b700b6 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -1,7 +1,7 @@ use rustc::hir::def_id::DefId; use rustc::mir::*; use rustc::ty::TyCtxt; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use std::fmt::Debug; use std::io::{self, Write}; diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 9757f4ac392ec..b42eebc7ee3be 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -30,8 +30,8 @@ use rustc::mir::visit::{ use rustc::mir::Local; use rustc::mir::*; use rustc::ty::{self, TyCtxt}; -use rustc_index::bit_set::BitSet; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::bit_set::BitSet; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::work_queue::WorkQueue; use std::fs; use std::io::{self, Write}; diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index a5f7e5401573b..2ea9924af7f28 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -1,6 +1,6 @@ use rustc::ty::Ty; use rustc::mir::*; -use rustc_index::vec::{IndexVec, Idx}; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use syntax_pos::Span; /// This struct represents a patch to MIR, which can add diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 7f6b60b1b116b..c35c9e4da9f48 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -3,7 +3,7 @@ use rustc::mir::*; use rustc::mir::visit::Visitor; use rustc::ty::{self, TyCtxt}; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use std::fmt::Display; use std::fmt::Write as _; use std::fs; diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index 118deb560d62f..596ec6c19bcbf 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -13,8 +13,5 @@ log = "0.4" rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } syntax = { path = "../libsyntax" } -syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } errors = { path = "../librustc_errors", package = "rustc_errors" } -rustc_target = { path = "../librustc_target" } -rustc_index = { path = "../librustc_index" } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 74de31263d394..0339b85ca55e3 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -14,7 +14,7 @@ use rustc::session::Session; use rustc_data_structures::fx::FxHashMap; use syntax::ast::*; use syntax::attr; -use syntax_expand::proc_macro::is_proc_macro_attr; +use syntax::ext::proc_macro::is_proc_macro_attr; use syntax::feature_gate::is_builtin_attr; use syntax::source_map::Spanned; use syntax::symbol::{kw, sym}; @@ -263,8 +263,7 @@ impl<'a> AstValidator<'a> { let mut err = self.err_handler().struct_span_err(poly.span, &format!("`?Trait` is not permitted in {}", where_)); if is_trait { - let path_str = pprust::path_to_string(&poly.trait_ref.path); - err.note(&format!("traits are `?{}` by default", path_str)); + err.note(&format!("traits are `?{}` by default", poly.trait_ref.path)); } err.emit(); } diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index a2626617afec3..af07c790e2a87 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -1,15 +1,12 @@ syntax::register_diagnostics! { +/* E0014: r##" -#### Note: this error code is no longer emitted by the compiler. - Constants can only be initialized by a constant value or, in a future version of Rust, a call to a const function. This error indicates the use of a path (like a::b, or x) denoting something other than one of these -allowed items. - -Erroneous code example: +allowed items. Erroneous code xample: -``` +```compile_fail const FOO: i32 = { let x = 0; x }; // 'x' isn't a constant nor a function! ``` @@ -21,10 +18,10 @@ const FOO: i32 = { const X : i32 = 0; X }; const FOO2: i32 = { 0 }; // but brackets are useless here ``` "##, +*/ E0130: r##" You declared a pattern as an argument in a foreign function declaration. - Erroneous code example: ```compile_fail @@ -56,81 +53,6 @@ extern { ``` "##, -// This shouldn't really ever trigger since the repeated value error comes first -E0136: r##" -A binary can only have one entry point, and by default that entry point is the -function `main()`. If there are multiple such functions, please rename one. - -Erroneous code example: - -```compile_fail,E0136 -fn main() { - // ... -} - -// ... - -fn main() { // error! - // ... -} -``` -"##, - -E0137: r##" -More than one function was declared with the `#[main]` attribute. - -Erroneous code example: - -```compile_fail,E0137 -#![feature(main)] - -#[main] -fn foo() {} - -#[main] -fn f() {} // error: multiple functions with a `#[main]` attribute -``` - -This error indicates that the compiler found multiple functions with the -`#[main]` attribute. This is an error because there must be a unique entry -point into a Rust program. Example: - -``` -#![feature(main)] - -#[main] -fn f() {} // ok! -``` -"##, - -E0138: r##" -More than one function was declared with the `#[start]` attribute. - -Erroneous code example: - -```compile_fail,E0138 -#![feature(start)] - -#[start] -fn foo(argc: isize, argv: *const *const u8) -> isize {} - -#[start] -fn f(argc: isize, argv: *const *const u8) -> isize {} -// error: multiple 'start' functions -``` - -This error indicates that the compiler found multiple functions with the -`#[start]` attribute. This is an error because there must be a unique entry -point into a Rust program. Example: - -``` -#![feature(start)] - -#[start] -fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok! -``` -"##, - E0197: r##" Inherent implementations (one that do not implement a trait but provide methods associated with a type) are always safe because they are not @@ -276,115 +198,20 @@ impl Foo for Bar { ``` "##, -E0512: r##" -Transmute with two differently sized types was attempted. Erroneous code -example: - -```compile_fail,E0512 -fn takes_u8(_: u8) {} - -fn main() { - unsafe { takes_u8(::std::mem::transmute(0u16)); } - // error: cannot transmute between types of different sizes, - // or dependently-sized types -} -``` - -Please use types with same size or use the expected type directly. Example: - -``` -fn takes_u8(_: u8) {} - -fn main() { - unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok! - // or: - unsafe { takes_u8(0u8); } // ok! -} -``` -"##, - -E0561: r##" -A non-ident or non-wildcard pattern has been used as a parameter of a function -pointer type. - -Erroneous code example: - -```compile_fail,E0561 -type A1 = fn(mut param: u8); // error! -type A2 = fn(¶m: u32); // error! -``` - -When using an alias over a function type, you cannot e.g. denote a parameter as -being mutable. - -To fix the issue, remove patterns (`_` is allowed though). Example: - -``` -type A1 = fn(param: u8); // ok! -type A2 = fn(_: u32); // ok! -``` - -You can also omit the parameter name: - -``` -type A3 = fn(i16); // ok! -``` -"##, - -E0567: r##" -Generics have been used on an auto trait. - -Erroneous code example: -```compile_fail,E0567 -#![feature(optin_builtin_traits)] - -auto trait Generic {} // error! - -fn main() {} -``` - -Since an auto trait is implemented on all existing types, the -compiler would not be able to infer the types of the trait's generic -parameters. - -To fix this issue, just remove the generics: - -``` -#![feature(optin_builtin_traits)] - -auto trait Generic {} // ok! - -fn main() {} -``` -"##, - -E0568: r##" -A super trait has been added to an auto trait. - -Erroneous code example: - -```compile_fail,E0568 -#![feature(optin_builtin_traits)] +E0590: r##" +`break` or `continue` must include a label when used in the condition of a +`while` loop. -auto trait Bound : Copy {} // error! +Example of erroneous code: -fn main() {} +```compile_fail +while break {} ``` -Since an auto trait is implemented on all existing types, adding a super trait -would filter out a lot of those types. In the current example, almost none of -all the existing types could implement `Bound` because very few of them have the -`Copy` trait. - -To fix this issue, just remove the super trait: - +To fix this, add a label specifying which loop is being broken out of: ``` -#![feature(optin_builtin_traits)] - -auto trait Bound {} // ok! - -fn main() {} +'foo: while break 'foo {} ``` "##, @@ -422,115 +249,6 @@ let result = loop { // ok! ``` "##, -E0590: r##" -`break` or `continue` must include a label when used in the condition of a -`while` loop. - -Example of erroneous code: - -```compile_fail -while break {} -``` - -To fix this, add a label specifying which loop is being broken out of: -``` -'foo: while break 'foo {} -``` -"##, - -E0591: r##" -Per [RFC 401][rfc401], if you have a function declaration `foo`: - -``` -// For the purposes of this explanation, all of these -// different kinds of `fn` declarations are equivalent: -struct S; -fn foo(x: S) { /* ... */ } -# #[cfg(for_demonstration_only)] -extern "C" { fn foo(x: S); } -# #[cfg(for_demonstration_only)] -impl S { fn foo(self) { /* ... */ } } -``` - -the type of `foo` is **not** `fn(S)`, as one might expect. -Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`. -However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`, -so you rarely notice this: - -``` -# struct S; -# fn foo(_: S) {} -let x: fn(S) = foo; // OK, coerces -``` - -The reason that this matter is that the type `fn(S)` is not specific to -any particular function: it's a function _pointer_. So calling `x()` results -in a virtual call, whereas `foo()` is statically dispatched, because the type -of `foo` tells us precisely what function is being called. - -As noted above, coercions mean that most code doesn't have to be -concerned with this distinction. However, you can tell the difference -when using **transmute** to convert a fn item into a fn pointer. - -This is sometimes done as part of an FFI: - -```compile_fail,E0591 -extern "C" fn foo(userdata: Box) { - /* ... */ -} - -# fn callback(_: extern "C" fn(*mut i32)) {} -# use std::mem::transmute; -# unsafe { -let f: extern "C" fn(*mut i32) = transmute(foo); -callback(f); -# } -``` - -Here, transmute is being used to convert the types of the fn arguments. -This pattern is incorrect because, because the type of `foo` is a function -**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`) -is a function pointer, which is not zero-sized. -This pattern should be rewritten. There are a few possible ways to do this: - -- change the original fn declaration to match the expected signature, - and do the cast in the fn body (the preferred option) -- cast the fn item fo a fn pointer before calling transmute, as shown here: - - ``` - # extern "C" fn foo(_: Box) {} - # use std::mem::transmute; - # unsafe { - let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); - let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too - # } - ``` - -The same applies to transmutes to `*mut fn()`, which were observed in practice. -Note though that use of this type is generally incorrect. -The intention is typically to describe a function pointer, but just `fn()` -alone suffices for that. `*mut fn()` is a pointer to a fn pointer. -(Since these values are typically just passed to C code, however, this rarely -makes a difference in practice.) - -[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md -"##, - -E0601: r##" -No `main` function was found in a binary crate. To fix this error, add a -`main` function. For example: - -``` -fn main() { - // Your program will start here. - println!("Hello world!"); -} -``` - -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/ -"##, - E0642: r##" Trait methods currently cannot take patterns as arguments. @@ -601,10 +319,12 @@ async fn foo() {} Switch to the Rust 2018 edition to use `async fn`. "##, - ; 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 + E0567, // auto traits can not have generic parameters + E0568, // auto traits can not have super traits E0666, // nested `impl Trait` is illegal E0667, // `impl Trait` in projections E0696, // `continue` pointing to a labeled block diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index db59d8e101f77..4e29706714f3d 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -13,27 +13,18 @@ #[macro_use] extern crate rustc; -#[macro_use] -extern crate log; -#[macro_use] -extern crate syntax; use rustc::ty::query::Providers; pub mod error_codes; pub mod ast_validation; +pub mod rvalue_promotion; pub mod hir_stats; pub mod layout_test; pub mod loops; -pub mod dead; -pub mod entry; -mod liveness; -mod intrinsicck; pub fn provide(providers: &mut Providers<'_>) { - entry::provide(providers); + rvalue_promotion::provide(providers); loops::provide(providers); - liveness::provide(providers); - intrinsicck::provide(providers); } diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs new file mode 100644 index 0000000000000..a93ca7847d68a --- /dev/null +++ b/src/librustc_passes/rvalue_promotion.rs @@ -0,0 +1,658 @@ +// Verifies that the types and values of const and static items +// are safe. The rules enforced by this module are: +// +// - For each *mutable* static item, it checks that its **type**: +// - doesn't have a destructor +// - doesn't own a box +// +// - For each *immutable* static item, it checks that its **value**: +// - doesn't own a box +// - doesn't contain a struct literal or a call to an enum variant / struct constructor where +// - the type of the struct/enum has a dtor +// +// Rules Enforced Elsewhere: +// - It's not possible to take the address of a static item with unsafe interior. This is enforced +// by borrowck::gather_loans + +use rustc::ty::cast::CastTy; +use rustc::hir::def::{Res, DefKind, CtorKind}; +use rustc::hir::def_id::DefId; +use rustc::middle::expr_use_visitor as euv; +use rustc::middle::mem_categorization as mc; +use rustc::middle::mem_categorization::Categorization; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::query::Providers; +use rustc::ty::subst::{InternalSubsts, SubstsRef}; +use rustc::util::nodemap::{ItemLocalSet, HirIdSet}; +use rustc::hir; +use syntax::symbol::sym; +use syntax_pos::{Span, DUMMY_SP}; +use log::debug; +use Promotability::*; +use std::ops::{BitAnd, BitAndAssign, BitOr}; + +pub fn provide(providers: &mut Providers<'_>) { + *providers = Providers { + rvalue_promotable_map, + const_is_rvalue_promotable_to_static, + ..*providers + }; +} + +fn const_is_rvalue_promotable_to_static(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + assert!(def_id.is_local()); + + let hir_id = tcx.hir().as_local_hir_id(def_id) + .expect("rvalue_promotable_map invoked with non-local def-id"); + let body_id = tcx.hir().body_owned_by(hir_id); + tcx.rvalue_promotable_map(def_id).contains(&body_id.hir_id.local_id) +} + +fn rvalue_promotable_map(tcx: TyCtxt<'_>, def_id: DefId) -> &ItemLocalSet { + let outer_def_id = tcx.closure_base_def_id(def_id); + if outer_def_id != def_id { + return tcx.rvalue_promotable_map(outer_def_id); + } + + let mut visitor = CheckCrateVisitor { + tcx, + tables: &ty::TypeckTables::empty(None), + in_fn: false, + in_static: false, + mut_rvalue_borrows: Default::default(), + param_env: ty::ParamEnv::empty(), + identity_substs: InternalSubsts::empty(), + result: ItemLocalSet::default(), + }; + + // `def_id` should be a `Body` owner + let hir_id = tcx.hir().as_local_hir_id(def_id) + .expect("rvalue_promotable_map invoked with non-local def-id"); + let body_id = tcx.hir().body_owned_by(hir_id); + let _ = visitor.check_nested_body(body_id); + + tcx.arena.alloc(visitor.result) +} + +struct CheckCrateVisitor<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + in_fn: bool, + in_static: bool, + mut_rvalue_borrows: HirIdSet, + param_env: ty::ParamEnv<'tcx>, + identity_substs: SubstsRef<'tcx>, + tables: &'a ty::TypeckTables<'tcx>, + result: ItemLocalSet, +} + +#[must_use] +#[derive(Debug, Clone, Copy, PartialEq)] +enum Promotability { + Promotable, + NotPromotable +} + +impl BitAnd for Promotability { + type Output = Self; + + fn bitand(self, rhs: Self) -> Self { + match (self, rhs) { + (Promotable, Promotable) => Promotable, + _ => NotPromotable, + } + } +} + +impl BitAndAssign for Promotability { + fn bitand_assign(&mut self, rhs: Self) { + *self = *self & rhs + } +} + +impl BitOr for Promotability { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self { + match (self, rhs) { + (NotPromotable, NotPromotable) => NotPromotable, + _ => Promotable, + } + } +} + +impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { + // Returns true iff all the values of the type are promotable. + fn type_promotability(&mut self, ty: Ty<'tcx>) -> Promotability { + debug!("type_promotability({})", ty); + + if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) && + !ty.needs_drop(self.tcx, self.param_env) { + Promotable + } else { + NotPromotable + } + } + + fn handle_const_fn_call( + &mut self, + def_id: DefId, + ) -> Promotability { + if self.tcx.is_promotable_const_fn(def_id) { + Promotable + } else { + NotPromotable + } + } + + /// While the `ExprUseVisitor` walks, we will identify which + /// expressions are borrowed, and insert their IDs into this + /// table. Actually, we insert the "borrow-id", which is normally + /// the ID of the expression being borrowed: but in the case of + /// `ref mut` borrows, the `id` of the pattern is + /// inserted. Therefore, later we remove that entry from the table + /// and transfer it over to the value being matched. This will + /// then prevent said value from being promoted. + fn remove_mut_rvalue_borrow(&mut self, pat: &hir::Pat) -> bool { + let mut any_removed = false; + pat.walk(|p| { + any_removed |= self.mut_rvalue_borrows.remove(&p.hir_id); + true + }); + any_removed + } +} + +impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { + fn check_nested_body(&mut self, body_id: hir::BodyId) -> Promotability { + let item_id = self.tcx.hir().body_owner(body_id); + let item_def_id = self.tcx.hir().local_def_id(item_id); + + let outer_in_fn = self.in_fn; + let outer_tables = self.tables; + let outer_param_env = self.param_env; + let outer_identity_substs = self.identity_substs; + + self.in_fn = false; + self.in_static = false; + + match self.tcx.hir().body_owner_kind(item_id) { + hir::BodyOwnerKind::Closure | + hir::BodyOwnerKind::Fn => self.in_fn = true, + hir::BodyOwnerKind::Static(_) => self.in_static = true, + _ => {} + }; + + + self.tables = self.tcx.typeck_tables_of(item_def_id); + self.param_env = self.tcx.param_env(item_def_id); + self.identity_substs = InternalSubsts::identity_for_item(self.tcx, item_def_id); + + let body = self.tcx.hir().body(body_id); + + let tcx = self.tcx; + let param_env = self.param_env; + let region_scope_tree = self.tcx.region_scope_tree(item_def_id); + let tables = self.tables; + euv::ExprUseVisitor::new( + self, + tcx, + item_def_id, + param_env, + ®ion_scope_tree, + tables, + None, + ).consume_body(body); + + let body_promotable = self.check_expr(&body.value); + self.in_fn = outer_in_fn; + self.tables = outer_tables; + self.param_env = outer_param_env; + self.identity_substs = outer_identity_substs; + body_promotable + } + + fn check_stmt(&mut self, stmt: &'tcx hir::Stmt) -> Promotability { + match stmt.kind { + hir::StmtKind::Local(ref local) => { + if self.remove_mut_rvalue_borrow(&local.pat) { + if let Some(init) = &local.init { + self.mut_rvalue_borrows.insert(init.hir_id); + } + } + + if let Some(ref expr) = local.init { + let _ = self.check_expr(&expr); + } + NotPromotable + } + // Item statements are allowed + hir::StmtKind::Item(..) => Promotable, + hir::StmtKind::Expr(ref box_expr) | + hir::StmtKind::Semi(ref box_expr) => { + let _ = self.check_expr(box_expr); + NotPromotable + } + } + } + + fn check_expr(&mut self, ex: &'tcx hir::Expr) -> Promotability { + let node_ty = self.tables.node_type(ex.hir_id); + let mut outer = check_expr_kind(self, ex, node_ty); + outer &= check_adjustments(self, ex); + + // Handle borrows on (or inside the autorefs of) this expression. + if self.mut_rvalue_borrows.remove(&ex.hir_id) { + outer = NotPromotable + } + + if outer == Promotable { + self.result.insert(ex.hir_id.local_id); + } + outer + } + + fn check_block(&mut self, block: &'tcx hir::Block) -> Promotability { + let mut iter_result = Promotable; + for index in block.stmts.iter() { + iter_result &= self.check_stmt(index); + } + match block.expr { + Some(ref box_expr) => iter_result & self.check_expr(&*box_expr), + None => iter_result, + } + } +} + +/// This function is used to enforce the constraints on +/// const/static items. It walks through the *value* +/// of the item walking down the expression and evaluating +/// every nested expression. If the expression is not part +/// of a const/static item, it is qualified for promotion +/// instead of producing errors. +fn check_expr_kind<'a, 'tcx>( + v: &mut CheckCrateVisitor<'a, 'tcx>, + e: &'tcx hir::Expr, node_ty: Ty<'tcx>) -> Promotability { + + let ty_result = match node_ty.kind { + ty::Adt(def, _) if def.has_dtor(v.tcx) => { + NotPromotable + } + _ => Promotable + }; + + let kind_result = match e.kind { + hir::ExprKind::Box(ref expr) => { + let _ = v.check_expr(&expr); + NotPromotable + } + hir::ExprKind::Unary(op, ref expr) => { + let expr_promotability = v.check_expr(expr); + if v.tables.is_method_call(e) || op == hir::UnDeref { + return NotPromotable; + } + expr_promotability + } + hir::ExprKind::Binary(op, ref lhs, ref rhs) => { + let lefty = v.check_expr(lhs); + let righty = v.check_expr(rhs); + if v.tables.is_method_call(e) { + return NotPromotable; + } + match v.tables.node_type(lhs.hir_id).kind { + ty::RawPtr(_) | ty::FnPtr(..) => { + assert!(op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne || + op.node == hir::BinOpKind::Le || op.node == hir::BinOpKind::Lt || + op.node == hir::BinOpKind::Ge || op.node == hir::BinOpKind::Gt); + + NotPromotable + } + _ => lefty & righty + } + } + hir::ExprKind::Cast(ref from, _) => { + let expr_promotability = v.check_expr(from); + debug!("checking const cast(id={})", from.hir_id); + let cast_in = CastTy::from_ty(v.tables.expr_ty(from)); + let cast_out = CastTy::from_ty(v.tables.expr_ty(e)); + match (cast_in, cast_out) { + (Some(CastTy::FnPtr), Some(CastTy::Int(_))) | + (Some(CastTy::Ptr(_)), Some(CastTy::Int(_))) => NotPromotable, + (_, _) => expr_promotability + } + } + hir::ExprKind::Path(ref qpath) => { + let res = v.tables.qpath_res(qpath, e.hir_id); + match res { + Res::Def(DefKind::Ctor(..), _) + | Res::Def(DefKind::Fn, _) + | Res::Def(DefKind::Method, _) + | Res::SelfCtor(..) => + Promotable, + + // References to a static that are themselves within a static + // are inherently promotable with the exception + // of "#[thread_local]" statics, which may not + // outlive the current function + Res::Def(DefKind::Static, did) => { + + if v.in_static { + for attr in &v.tcx.get_attrs(did)[..] { + if attr.check_name(sym::thread_local) { + debug!("reference to `Static(id={:?})` is unpromotable \ + due to a `#[thread_local]` attribute", did); + return NotPromotable; + } + } + Promotable + } else { + debug!("reference to `Static(id={:?})` is unpromotable as it is not \ + referenced from a static", did); + NotPromotable + } + } + + Res::Def(DefKind::Const, did) | + Res::Def(DefKind::AssocConst, did) => { + let promotable = if v.tcx.trait_of_item(did).is_some() { + // Don't peek inside trait associated constants. + NotPromotable + } else if v.tcx.at(e.span).const_is_rvalue_promotable_to_static(did) { + Promotable + } else { + NotPromotable + }; + // Just in case the type is more specific than the definition, + // e.g., impl associated const with type parameters, check it. + // Also, trait associated consts are relaxed by this. + promotable | v.type_promotability(node_ty) + } + _ => NotPromotable + } + } + hir::ExprKind::Call(ref callee, ref hirvec) => { + let mut call_result = v.check_expr(callee); + for index in hirvec.iter() { + call_result &= v.check_expr(index); + } + let mut callee = &**callee; + loop { + callee = match callee.kind { + hir::ExprKind::Block(ref block, _) => match block.expr { + Some(ref tail) => &tail, + None => break + }, + _ => break + }; + } + // The callee is an arbitrary expression, it doesn't necessarily have a definition. + let def = if let hir::ExprKind::Path(ref qpath) = callee.kind { + v.tables.qpath_res(qpath, callee.hir_id) + } else { + Res::Err + }; + let def_result = match def { + Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | + Res::SelfCtor(..) => Promotable, + Res::Def(DefKind::Fn, did) => v.handle_const_fn_call(did), + Res::Def(DefKind::Method, did) => { + match v.tcx.associated_item(did).container { + ty::ImplContainer(_) => v.handle_const_fn_call(did), + ty::TraitContainer(_) => NotPromotable, + } + } + _ => NotPromotable, + }; + def_result & call_result + } + hir::ExprKind::MethodCall(ref _pathsegment, ref _span, ref hirvec) => { + let mut method_call_result = Promotable; + for index in hirvec.iter() { + method_call_result &= v.check_expr(index); + } + if let Some(def_id) = v.tables.type_dependent_def_id(e.hir_id) { + match v.tcx.associated_item(def_id).container { + ty::ImplContainer(_) => method_call_result & v.handle_const_fn_call(def_id), + ty::TraitContainer(_) => NotPromotable, + } + } else { + v.tcx.sess.delay_span_bug(e.span, "no type-dependent def for method call"); + NotPromotable + } + } + hir::ExprKind::Struct(ref _qpath, ref hirvec, ref option_expr) => { + let mut struct_result = Promotable; + for index in hirvec.iter() { + struct_result &= v.check_expr(&index.expr); + } + if let Some(ref expr) = *option_expr { + struct_result &= v.check_expr(&expr); + } + if let ty::Adt(adt, ..) = v.tables.expr_ty(e).kind { + // unsafe_cell_type doesn't necessarily exist with no_core + if Some(adt.did) == v.tcx.lang_items().unsafe_cell_type() { + return NotPromotable; + } + } + struct_result + } + + hir::ExprKind::Lit(_) | + hir::ExprKind::Err => Promotable, + + hir::ExprKind::AddrOf(_, ref expr) | + hir::ExprKind::Repeat(ref expr, _) | + hir::ExprKind::Type(ref expr, _) | + hir::ExprKind::DropTemps(ref expr) => { + v.check_expr(&expr) + } + + hir::ExprKind::Closure(_capture_clause, ref _box_fn_decl, + body_id, _span, _option_generator_movability) => { + let nested_body_promotable = v.check_nested_body(body_id); + // Paths in constant contexts cannot refer to local variables, + // as there are none, and thus closures can't have upvars there. + let closure_def_id = v.tcx.hir().local_def_id(e.hir_id); + if !v.tcx.upvars(closure_def_id).map_or(true, |v| v.is_empty()) { + NotPromotable + } else { + nested_body_promotable + } + } + + hir::ExprKind::Field(ref expr, _ident) => { + let expr_promotability = v.check_expr(&expr); + if let Some(def) = v.tables.expr_ty(expr).ty_adt_def() { + if def.is_union() { + return NotPromotable; + } + } + expr_promotability + } + + hir::ExprKind::Block(ref box_block, ref _option_label) => { + v.check_block(box_block) + } + + hir::ExprKind::Index(ref lhs, ref rhs) => { + let lefty = v.check_expr(lhs); + let righty = v.check_expr(rhs); + if v.tables.is_method_call(e) { + return NotPromotable; + } + lefty & righty + } + + hir::ExprKind::Array(ref hirvec) => { + let mut array_result = Promotable; + for index in hirvec.iter() { + array_result &= v.check_expr(index); + } + array_result + } + + hir::ExprKind::Tup(ref hirvec) => { + let mut tup_result = Promotable; + for index in hirvec.iter() { + tup_result &= v.check_expr(index); + } + tup_result + } + + // Conditional control flow (possible to implement). + hir::ExprKind::Match(ref expr, ref arms, ref _match_source) => { + // Compute the most demanding borrow from all the arms' + // patterns and set that on the discriminator. + if arms.iter().fold(false, |_, arm| v.remove_mut_rvalue_borrow(&arm.pat)) { + v.mut_rvalue_borrows.insert(expr.hir_id); + } + + let _ = v.check_expr(expr); + for index in arms.iter() { + let _ = v.check_expr(&*index.body); + if let Some(hir::Guard::If(ref expr)) = index.guard { + let _ = v.check_expr(&expr); + } + } + NotPromotable + } + + hir::ExprKind::Loop(ref box_block, ref _option_label, ref _loop_source) => { + let _ = v.check_block(box_block); + NotPromotable + } + + // More control flow (also not very meaningful). + hir::ExprKind::Break(_, ref option_expr) | hir::ExprKind::Ret(ref option_expr) => { + if let Some(ref expr) = *option_expr { + let _ = v.check_expr(&expr); + } + NotPromotable + } + + hir::ExprKind::Continue(_) => { + NotPromotable + } + + // Generator expressions + hir::ExprKind::Yield(ref expr, _) => { + let _ = v.check_expr(&expr); + NotPromotable + } + + // Expressions with side-effects. + hir::ExprKind::AssignOp(_, ref lhs, ref rhs) | hir::ExprKind::Assign(ref lhs, ref rhs) => { + let _ = v.check_expr(lhs); + let _ = v.check_expr(rhs); + NotPromotable + } + + hir::ExprKind::InlineAsm(ref _inline_asm, ref hirvec_lhs, ref hirvec_rhs) => { + for index in hirvec_lhs.iter().chain(hirvec_rhs.iter()) { + let _ = v.check_expr(index); + } + NotPromotable + } + }; + ty_result & kind_result +} + +/// Checks the adjustments of an expression. +fn check_adjustments<'a, 'tcx>( + v: &mut CheckCrateVisitor<'a, 'tcx>, + e: &hir::Expr) -> Promotability { + use rustc::ty::adjustment::*; + + let mut adjustments = v.tables.expr_adjustments(e).iter().peekable(); + while let Some(adjustment) = adjustments.next() { + match adjustment.kind { + Adjust::NeverToAny | + Adjust::Pointer(_) | + Adjust::Borrow(_) => {} + + Adjust::Deref(_) => { + if let Some(next_adjustment) = adjustments.peek() { + if let Adjust::Borrow(_) = next_adjustment.kind { + continue; + } + } + return NotPromotable; + } + } + } + Promotable +} + +impl<'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> { + fn consume(&mut self, + _consume_id: hir::HirId, + _consume_span: Span, + _cmt: &mc::cmt_<'_>, + _mode: euv::ConsumeMode) {} + + fn borrow(&mut self, + borrow_id: hir::HirId, + _borrow_span: Span, + cmt: &mc::cmt_<'tcx>, + _loan_region: ty::Region<'tcx>, + bk: ty::BorrowKind, + loan_cause: euv::LoanCause) { + debug!( + "borrow(borrow_id={:?}, cmt={:?}, bk={:?}, loan_cause={:?})", + borrow_id, + cmt, + bk, + loan_cause, + ); + + // Kind of hacky, but we allow Unsafe coercions in constants. + // These occur when we convert a &T or *T to a *U, as well as + // when making a thin pointer (e.g., `*T`) into a fat pointer + // (e.g., `*Trait`). + if let euv::LoanCause::AutoUnsafe = loan_cause { + return; + } + + let mut cur = cmt; + loop { + match cur.cat { + Categorization::ThreadLocal(..) | + Categorization::Rvalue(..) => { + if loan_cause == euv::MatchDiscriminant { + // Ignore the dummy immutable borrow created by EUV. + break; + } + if bk.to_mutbl_lossy() == hir::MutMutable { + self.mut_rvalue_borrows.insert(borrow_id); + } + break; + } + Categorization::StaticItem => { + break; + } + Categorization::Deref(ref cmt, _) | + Categorization::Downcast(ref cmt, _) | + Categorization::Interior(ref cmt, _) => { + cur = cmt; + } + + Categorization::Upvar(..) | + Categorization::Local(..) => break, + } + } + } + + fn decl_without_init(&mut self, _id: hir::HirId, _span: Span) {} + fn mutate(&mut self, + _assignment_id: hir::HirId, + _assignment_span: Span, + _assignee_cmt: &mc::cmt_<'_>, + _mode: euv::MutateMode) { + } + + fn matched_pat(&mut self, _: &hir::Pat, _: &mc::cmt_<'_>, _: euv::MatchMode) {} + + fn consume_pat(&mut self, + _consume_pat: &hir::Pat, + _cmt: &mc::cmt_<'_>, + _mode: euv::ConsumeMode) {} +} diff --git a/src/librustc_plugin/Cargo.toml b/src/librustc_plugin/Cargo.toml index e8bf4e7ea8ff6..3f11430dc82cb 100644 --- a/src/librustc_plugin/Cargo.toml +++ b/src/librustc_plugin/Cargo.toml @@ -14,5 +14,4 @@ doctest = false rustc = { path = "../librustc" } rustc_metadata = { path = "../librustc_metadata" } syntax = { path = "../libsyntax" } -syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 38738e20630c9..4e1a47c503e59 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -21,7 +21,7 @@ //! extern crate syntax_pos; //! //! use rustc_driver::plugin::Registry; -//! use syntax_expand::base::{ExtCtxt, MacResult}; +//! use syntax::ext::base::{ExtCtxt, MacResult}; //! use syntax_pos::Span; //! use syntax::tokenstream::TokenTree; //! diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 8ceb56b0fd2b4..4481892bcf244 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -1,8 +1,8 @@ //! Used by `rustc` when loading a plugin. -use rustc::middle::cstore::MetadataLoader; use rustc::session::Session; -use rustc_metadata::locator; +use rustc_metadata::creader::CrateLoader; +use rustc_metadata::cstore::CStore; use crate::registry::Registry; use std::borrow::ToOwned; @@ -25,7 +25,7 @@ pub struct PluginRegistrar { struct PluginLoader<'a> { sess: &'a Session, - metadata_loader: &'a dyn MetadataLoader, + reader: CrateLoader<'a>, plugins: Vec, } @@ -37,10 +37,11 @@ fn call_malformed_plugin_attribute(sess: &Session, span: Span) { /// Read plugin metadata and dynamically load registrar functions. pub fn load_plugins(sess: &Session, - metadata_loader: &dyn MetadataLoader, + cstore: &CStore, krate: &ast::Crate, + crate_name: &str, addl_plugins: Option>) -> Vec { - let mut loader = PluginLoader { sess, metadata_loader, plugins: Vec::new() }; + let mut loader = PluginLoader::new(sess, cstore, crate_name); // do not report any error now. since crate attributes are // not touched by expansion, every use of plugin without @@ -79,8 +80,16 @@ pub fn load_plugins(sess: &Session, } impl<'a> PluginLoader<'a> { + fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> Self { + PluginLoader { + sess, + reader: CrateLoader::new(sess, cstore, crate_name), + plugins: vec![], + } + } + fn load_plugin(&mut self, span: Span, name: Symbol, args: Vec) { - let registrar = locator::find_plugin_registrar(self.sess, self.metadata_loader, span, name); + let registrar = self.reader.find_plugin_registrar(span, name); if let Some((lib, disambiguator)) = registrar { let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator); diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 2e23b8c870cfc..bb3c950edae3b 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -1,10 +1,11 @@ //! Used by plugin crates to tell `rustc` about the plugins they provide. -use rustc::lint::LintStore; +use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint}; use rustc::session::Session; +use rustc::util::nodemap::FxHashMap; -use syntax_expand::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension}; -use syntax_expand::base::MacroExpanderFn; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension}; +use syntax::ext::base::MacroExpanderFn; use syntax::symbol::Symbol; use syntax::ast; use syntax::feature_gate::AttributeType; @@ -25,9 +26,6 @@ pub struct Registry<'a> { /// from the plugin registrar. pub sess: &'a Session, - /// The `LintStore` allows plugins to register new lints. - pub lint_store: &'a mut LintStore, - #[doc(hidden)] pub args_hidden: Option>, @@ -37,6 +35,15 @@ pub struct Registry<'a> { #[doc(hidden)] pub syntax_exts: Vec, + #[doc(hidden)] + pub early_lint_passes: Vec, + + #[doc(hidden)] + pub late_lint_passes: Vec, + + #[doc(hidden)] + pub lint_groups: FxHashMap<&'static str, (Vec, Option<&'static str>)>, + #[doc(hidden)] pub llvm_passes: Vec, @@ -46,13 +53,15 @@ pub struct Registry<'a> { impl<'a> Registry<'a> { #[doc(hidden)] - pub fn new(sess: &'a Session, lint_store: &'a mut LintStore, krate_span: Span) -> Registry<'a> { + pub fn new(sess: &'a Session, krate_span: Span) -> Registry<'a> { Registry { sess, - lint_store, args_hidden: None, krate_span, syntax_exts: vec![], + early_lint_passes: vec![], + late_lint_passes: vec![], + lint_groups: FxHashMap::default(), llvm_passes: vec![], attributes: vec![], } @@ -90,6 +99,27 @@ impl<'a> Registry<'a> { self.register_syntax_extension(Symbol::intern(name), ext); } + /// Register a compiler lint pass. + pub fn register_early_lint_pass(&mut self, lint_pass: EarlyLintPassObject) { + self.early_lint_passes.push(lint_pass); + } + + /// Register a compiler lint pass. + pub fn register_late_lint_pass(&mut self, lint_pass: LateLintPassObject) { + self.late_lint_passes.push(lint_pass); + } + /// Register a lint group. + pub fn register_lint_group( + &mut self, + name: &'static str, + deprecated_name: Option<&'static str>, + to: Vec<&'static Lint> + ) { + self.lint_groups.insert(name, + (to.into_iter().map(|x| LintId::of(x)).collect(), + deprecated_name)); + } + /// Register an LLVM pass. /// /// Registration with LLVM itself is handled through static C++ objects with diff --git a/src/librustc_privacy/error_codes.rs b/src/librustc_privacy/error_codes.rs index 03afb547d3a22..67066466f1d22 100644 --- a/src/librustc_privacy/error_codes.rs +++ b/src/librustc_privacy/error_codes.rs @@ -1,9 +1,8 @@ syntax::register_diagnostics! { E0445: r##" -A private trait was used on a public type parameter bound. - -Erroneous code examples: +A private trait was used on a public type parameter bound. Erroneous code +examples: ```compile_fail,E0445 #![deny(private_in_public)] @@ -33,9 +32,7 @@ pub fn foo (t: T) {} // ok! "##, E0446: r##" -A private type was used in a public type signature. - -Erroneous code example: +A private type was used in a public type signature. Erroneous code example: ```compile_fail,E0446 #![deny(private_in_public)] @@ -68,9 +65,7 @@ mod Foo { E0447: r##" #### Note: this error code is no longer emitted by the compiler. -The `pub` keyword was used inside a function. - -Erroneous code example: +The `pub` keyword was used inside a function. Erroneous code example: ``` fn foo() { @@ -84,11 +79,7 @@ is invalid. "##, E0448: r##" -#### Note: this error code is no longer emitted by the compiler. - -The `pub` keyword was used inside a public enum. - -Erroneous code example: +The `pub` keyword was used inside a public enum. Erroneous code example: ```compile_fail pub enum Foo { @@ -115,9 +106,7 @@ pub enum Foo { "##, E0451: r##" -A struct constructor with private fields was invoked. - -Erroneous code example: +A struct constructor with private fields was invoked. Erroneous code example: ```compile_fail,E0451 mod Bar { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 34cdec229af43..f44692b7aea7d 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -64,7 +64,7 @@ trait DefIdVisitor<'tcx> { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { self.skeleton().visit_trait(trait_ref) } - fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> bool { + fn visit_predicates(&mut self, predicates: &ty::GenericPredicates<'tcx>) -> bool { self.skeleton().visit_predicates(predicates) } } @@ -88,7 +88,7 @@ where (!self.def_id_visitor.shallow() && substs.visit_with(self)) } - fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> bool { + fn visit_predicates(&mut self, predicates: &ty::GenericPredicates<'tcx>) -> bool { let ty::GenericPredicates { parent: _, predicates } = predicates; for (predicate, _span) in predicates { match predicate { @@ -880,11 +880,11 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { self.tcx, self.tcx.hir().local_def_id(md.hir_id) ).unwrap(); - let mut module_id = match self.tcx.hir().as_local_hir_id(macro_module_def_id) { - Some(module_id) if self.tcx.hir().is_hir_id_module(module_id) => module_id, - // `module_id` doesn't correspond to a `mod`, return early (#63164, #65252). - _ => return, - }; + 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() { diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml index 06bf30859898a..936e72ef2c571 100644 --- a/src/librustc_resolve/Cargo.toml +++ b/src/librustc_resolve/Cargo.toml @@ -14,7 +14,6 @@ doctest = false bitflags = "1.0" log = "0.4" syntax = { path = "../libsyntax" } -syntax_expand = { path = "../libsyntax_expand" } rustc = { path = "../librustc" } arena = { path = "../libarena" } errors = { path = "../librustc_errors", package = "rustc_errors" } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index c0fb8e33a819e..f76aa95dd2cc8 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -32,14 +32,12 @@ use syntax::attr; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId}; use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind}; -use syntax_expand::base::{MacroKind, SyntaxExtension}; -use syntax_expand::expand::AstFragment; -use syntax_expand::hygiene::ExpnId; +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}; -use syntax::print::pprust; use syntax::{span_err, struct_span_err}; -use syntax::source_map::{respan, Spanned}; use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; @@ -94,8 +92,7 @@ impl<'a> Resolver<'a> { where T: ToNameBinding<'a>, { let binding = def.to_name_binding(self.arenas); - let key = self.new_key(ident, ns); - if let Err(old_binding) = self.try_define(parent, key, binding) { + if let Err(old_binding) = self.try_define(parent, ident, ns, binding) { self.report_conflict(parent, ident, ns, old_binding, &binding); } } @@ -105,23 +102,24 @@ impl<'a> Resolver<'a> { return self.module_map[&def_id] } - if let Some(&module) = self.extern_module_map.get(&def_id) { + let macros_only = self.cstore.dep_kind_untracked(def_id.krate).macros_only(); + if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) { return module; } let (name, parent) = if def_id.index == CRATE_DEF_INDEX { - (self.cstore().crate_name_untracked(def_id.krate), None) + (self.cstore.crate_name_untracked(def_id.krate).as_interned_str(), None) } else { - let def_key = self.cstore().def_key(def_id); + let def_key = self.cstore.def_key(def_id); (def_key.disambiguated_data.data.get_opt_name().unwrap(), Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id }))) }; - let kind = ModuleKind::Def(DefKind::Mod, def_id, name); + let kind = ModuleKind::Def(DefKind::Mod, def_id, name.as_symbol()); let module = self.arenas.alloc_module(ModuleData::new( parent, kind, def_id, ExpnId::root(), DUMMY_SP )); - self.extern_module_map.insert(def_id, module); + self.extern_module_map.insert((def_id, macros_only), module); module } @@ -153,8 +151,9 @@ impl<'a> Resolver<'a> { return Some(ext.clone()); } - let ext = Lrc::new(match self.cstore().load_macro_untracked(def_id, &self.session) { - LoadedMacro::MacroDef(item, edition) => self.compile_macro(&item, edition), + 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, }); @@ -162,21 +161,31 @@ impl<'a> Resolver<'a> { Some(ext) } + // 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) { + for child in self.cstore.item_children_untracked(def_id, self.session) { let child = child.map_id(|_| panic!("unexpected id")); BuildReducedGraphVisitor { r: self, parent_scope: ParentScope::module(module) } .build_reduced_graph_for_external_crate_res(child); @@ -218,7 +227,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { .span_suggestion( path.span, "try", - format!("crate::{}", pprust::path_to_string(&path)), + format!("crate::{}", path), Applicability::MaybeIncorrect, ) .emit(); @@ -292,7 +301,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } } - fn insert_field_names(&mut self, def_id: DefId, field_names: Vec>) { + fn insert_field_names(&mut self, def_id: DefId, field_names: Vec) { if !field_names.is_empty() { self.r.field_names.insert(def_id, field_names); } @@ -339,12 +348,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.indeterminate_imports.push(directive); match directive.subclass { - // Don't add unresolved underscore imports to modules - SingleImport { target: Ident { name: kw::Underscore, .. }, .. } => {} SingleImport { target, type_ns_only, .. } => { self.r.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { - let key = this.new_key(target, ns); - let mut resolution = this.resolution(current_module, key).borrow_mut(); + let mut resolution = this.resolution(current_module, target, ns).borrow_mut(); resolution.add_single_import(directive); }); } @@ -400,7 +406,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }; match use_tree.kind { ast::UseTreeKind::Simple(rename, ..) => { - let mut ident = use_tree.ident(); + let mut ident = use_tree.ident().gensym_if_underscore(); let mut module_path = prefix; let mut source = module_path.pop().unwrap(); let mut type_ns_only = false; @@ -578,7 +584,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let parent_scope = &self.parent_scope; let parent = parent_scope.module; let expansion = parent_scope.expansion; - let ident = item.ident; + let ident = item.ident.gensym_if_underscore(); let sp = item.span; let vis = self.resolve_visibility(&item.vis); @@ -610,7 +616,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let crate_id = self.r.crate_loader.process_extern_crate( item, &self.r.definitions ); - self.r.extern_crate_map.insert(item.id, crate_id); self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) }; @@ -747,12 +752,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } // Record field names for error reporting. - let field_names = struct_def.fields().iter().map(|field| { + let field_names = struct_def.fields().iter().filter_map(|field| { let field_vis = self.resolve_visibility(&field.vis); if ctor_vis.is_at_least(field_vis, &*self.r) { ctor_vis = field_vis; } - respan(field.span, field.ident.map_or(kw::Invalid, |ident| ident.name)) + field.ident.map(|ident| ident.name) }).collect(); let item_def_id = self.r.definitions.local_def_id(item.id); self.insert_field_names(item_def_id, field_names); @@ -774,9 +779,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); // Record field names for error reporting. - let field_names = vdata.fields().iter().map(|field| { + let field_names = vdata.fields().iter().filter_map(|field| { self.resolve_visibility(&field.vis); - respan(field.span, field.ident.map_or(kw::Invalid, |ident| ident.name)) + field.ident.map(|ident| ident.name) }).collect(); let item_def_id = self.r.definitions.local_def_id(item.id); self.insert_field_names(item_def_id, field_names); @@ -844,6 +849,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { 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 { @@ -884,19 +893,18 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { bug!("unexpected resolution: {:?}", res) } // Record some extra data for better diagnostics. - let cstore = self.r.cstore(); match res { Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => { - let field_names = cstore.struct_field_names_untracked(def_id, self.r.session); + let field_names = self.r.cstore.struct_field_names_untracked(def_id); self.insert_field_names(def_id, field_names); } Res::Def(DefKind::Method, def_id) => { - if cstore.associated_item_cloned_untracked(def_id).method_has_self_argument { + 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 = cstore.def_key(def_id).parent; + 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)); } @@ -1053,17 +1061,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { None } - // Mark the given macro as unused unless its name starts with `_`. - // Macro uses will remove items from this set, and the remaining - // items will be reported as `unused_macros`. - fn insert_unused_macro(&mut self, ident: Ident, node_id: NodeId, span: Span) { - if !ident.as_str().starts_with("_") { - self.r.unused_macros.insert(node_id, span); - } - } - fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> { - let parent_scope = self.parent_scope; + let parent_scope = &self.parent_scope; let expansion = parent_scope.expansion; let (ext, ident, span, is_legacy) = match &item.kind { ItemKind::MacroDef(def) => { @@ -1103,7 +1102,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { (res, vis, span, expansion, IsMacroExport)); } else { self.r.check_reserved_macro_name(ident, res); - self.insert_unused_macro(ident, item.id, span); + self.r.unused_macros.insert(item.id, span); } LegacyScope::Binding(self.r.arenas.alloc_legacy_binding(LegacyBinding { parent_legacy_scope: parent_scope.legacy, binding, ident @@ -1112,7 +1111,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let module = parent_scope.module; let vis = self.resolve_visibility(&item.vis); if vis != ty::Visibility::Public { - self.insert_unused_macro(ident, item.id, span); + self.r.unused_macros.insert(item.id, span); } self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); self.parent_scope.legacy diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 7634093fbefba..c479912b4ef81 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -10,7 +10,7 @@ use rustc::session::Session; use rustc::ty::{self, DefIdTree}; use rustc::util::nodemap::FxHashSet; use syntax::ast::{self, Ident, Path}; -use syntax_expand::base::MacroKind; +use syntax::ext::base::MacroKind; use syntax::feature_gate::BUILTIN_ATTRIBUTES; use syntax::source_map::SourceMap; use syntax::struct_span_err; @@ -20,7 +20,7 @@ use syntax_pos::{BytePos, Span, MultiSpan}; use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver}; use crate::{path_names_to_string, KNOWN_TOOLS}; -use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot}; +use crate::{BindingError, CrateLint, LegacyScope, Module, ModuleOrUniformRoot}; use crate::{PathResult, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Segment}; type Res = def::Res; @@ -80,11 +80,11 @@ impl<'a> Resolver<'a> { names: &mut Vec, filter_fn: &impl Fn(Res) -> bool, ) { - for (key, resolution) in self.resolutions(module).borrow().iter() { + 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(key.ident.name, res)); + names.push(TypoSuggestion::from_res(ident.name, res)); } } } @@ -102,7 +102,7 @@ impl<'a> Resolver<'a> { &self, span: Span, resolution_error: ResolutionError<'_> ) -> DiagnosticBuilder<'_> { match resolution_error { - ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => { + ResolutionError::GenericParamsFromOuterFunction(outer_res) => { let mut err = struct_span_err!(self.session, span, E0401, @@ -148,24 +148,22 @@ impl<'a> Resolver<'a> { } } - if has_generic_params == HasGenericParams::Yes { - // Try to retrieve the span of the function signature and generate a new - // message with a local type or const parameter. - let sugg_msg = &format!("try using a local generic parameter instead"); - if let Some((sugg_span, snippet)) = cm.generate_local_type_param_snippet(span) { - // Suggest the modification to the user - err.span_suggestion( - sugg_span, - sugg_msg, - snippet, - Applicability::MachineApplicable, - ); - } else if let Some(sp) = cm.generate_fn_name_span(span) { - err.span_label(sp, - format!("try adding a local generic parameter in this method instead")); - } else { - err.help(&format!("try using a local generic parameter instead")); - } + // Try to retrieve the span of the function signature and generate a new message + // with a local type or const parameter. + let sugg_msg = &format!("try using a local generic parameter instead"); + if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) { + // Suggest the modification to the user + err.span_suggestion( + sugg_span, + sugg_msg, + new_snippet, + Applicability::MachineApplicable, + ); + } else if let Some(sp) = cm.generate_fn_name_span(span) { + err.span_label(sp, + format!("try adding a local generic parameter in this method instead")); + } else { + err.help(&format!("try using a local generic parameter instead")); } err @@ -356,15 +354,14 @@ impl<'a> Resolver<'a> { span, "defaulted type parameters cannot be forward declared".to_string()); err } - ResolutionError::SelfInTyParamDefault => { + ResolutionError::ConstParamDependentOnTypeParam => { let mut err = struct_span_err!( self.session, span, - E0735, - "type parameters cannot use `Self` in their defaults" + E0671, + "const parameters cannot depend on type parameters" ); - err.span_label( - span, "`Self` in type parameter default".to_string()); + err.span_label(span, format!("const parameter depends on type parameter")); err } } @@ -519,7 +516,7 @@ impl<'a> Resolver<'a> { in_module_is_extern)) = worklist.pop() { // We have to visit module children in deterministic order to avoid // instabilities in reported imports (#43552). - in_module.for_each_child(self, |this, 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 @@ -839,7 +836,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } let resolutions = self.r.resolutions(crate_module).borrow(); - let resolution = resolutions.get(&self.r.new_key(ident, MacroNS))?; + let resolution = resolutions.get(&(ident, MacroNS))?; let binding = resolution.borrow().binding()?; if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() { let module_name = crate_module.kind.name().unwrap(); diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index be2e9f505aa6f..9a39fcf422393 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -8,9 +8,9 @@ Type parameter defaults can only use parameters that occur before them. Erroneous code example: ```compile_fail,E0128 -struct Foo { +struct Foo { field1: T, - field2: U, + filed2: U, } // error: type parameters with a default cannot use forward declared // identifiers @@ -20,9 +20,9 @@ Since type parameters are evaluated in-order, you may be able to fix this issue by doing: ``` -struct Foo { +struct Foo { field1: T, - field2: U, + filed2: U, } ``` @@ -1013,8 +1013,7 @@ fn h1() -> i32 { "##, E0424: r##" -The `self` keyword was used inside of an associated function without a "`self` -receiver" parameter. +The `self` keyword was used in a static method. Erroneous code example: @@ -1022,33 +1021,25 @@ Erroneous code example: struct Foo; impl Foo { - // `bar` is a method, because it has a receiver parameter. - fn bar(&self) {} + fn bar(self) {} - // `foo` is not a method, because it has no receiver parameter. fn foo() { - self.bar(); // error: `self` value is a keyword only available in - // methods with a `self` parameter + self.bar(); // error: `self` is not available in a static method. } } ``` -The `self` keyword can only be used inside methods, which are associated -functions (functions defined inside of a `trait` or `impl` block) that have a -`self` receiver as its first parameter, like `self`, `&self`, `&mut self` or -`self: &mut Pin` (this last one is an example of an ["abitrary `self` -type"](https://github.com/rust-lang/rust/issues/44874)). - -Check if the associated function's parameter list should have contained a `self` -receiver for it to be a method, and add it if so. Example: +Please check if the method's argument list should have contained `self`, +`&self`, or `&mut self` (in case you didn't want to create a static +method), and add it if so. Example: ``` struct Foo; impl Foo { - fn bar(&self) {} + fn bar(self) {} - fn foo(self) { // `foo` is now a method. + fn foo(self) { self.bar(); // ok! } } @@ -1620,208 +1611,6 @@ fn print_on_failure(state: &State) { ``` "##, -E0573: r##" -Something other than a type has been used when one was expected. - -Erroneous code examples: - -```compile_fail,E0573 -enum Dragon { - Born, -} - -fn oblivion() -> Dragon::Born { // error! - Dragon::Born -} - -const HOBBIT: u32 = 2; -impl HOBBIT {} // error! - -enum Wizard { - Gandalf, - Saruman, -} - -trait Isengard { - fn wizard(_: Wizard::Saruman); // error! -} -``` - -In all these errors, a type was expected. For example, in the first error, if -we want to return the `Born` variant from the `Dragon` enum, we must set the -function to return the enum and not its variant: - -``` -enum Dragon { - Born, -} - -fn oblivion() -> Dragon { // ok! - Dragon::Born -} -``` - -In the second error, you can't implement something on an item, only on types. -We would need to create a new type if we wanted to do something similar: - -``` -struct Hobbit(u32); // we create a new type - -const HOBBIT: Hobbit = Hobbit(2); -impl Hobbit {} // ok! -``` - -In the third case, we tried to only expect one variant of the `Wizard` enum, -which is not possible. To make this work, we need to using pattern matching -over the `Wizard` enum: - -``` -enum Wizard { - Gandalf, - Saruman, -} - -trait Isengard { - fn wizard(w: Wizard) { // ok! - match w { - Wizard::Saruman => { - // do something - } - _ => {} // ignore everything else - } - } -} -``` -"##, - -E0574: r##" -Something other than a struct, variant or union has been used when one was -expected. - -Erroneous code example: - -```compile_fail,E0574 -mod Mordor {} - -let sauron = Mordor { x: () }; // error! - -enum Jak { - Daxter { i: isize }, -} - -let eco = Jak::Daxter { i: 1 }; -match eco { - Jak { i } => {} // error! -} -``` - -In all these errors, a type was expected. For example, in the first error, -we tried to instantiate the `Mordor` module, which is impossible. If you want -to instantiate a type inside a module, you can do it as follow: - -``` -mod Mordor { - pub struct TheRing { - pub x: usize, - } -} - -let sauron = Mordor::TheRing { x: 1 }; // ok! -``` - -In the second error, we tried to bind the `Jak` enum directly, which is not -possible: you can only bind one of its variants. To do so: - -``` -enum Jak { - Daxter { i: isize }, -} - -let eco = Jak::Daxter { i: 1 }; -match eco { - Jak::Daxter { i } => {} // ok! -} -``` -"##, - -E0575: r##" -Something other than a type or an associated type was given. - -Erroneous code example: - -```compile_fail,E0575 -enum Rick { Morty } - -let _: ::Morty; // error! - -trait Age { - type Empire; - fn Mythology() {} -} - -impl Age for u8 { - type Empire = u16; -} - -let _: ::Mythology; // error! -``` - -In both cases, we're declaring a variable (called `_`) and we're giving it a -type. However, `::Morty` and `::Mythology` aren't types, -therefore the compiler throws an error. - -`::Morty` is an enum variant, you cannot use a variant as a type, -you have to use the enum directly: - -``` -enum Rick { Morty } - -let _: Rick; // ok! -``` - -`::Mythology` is a trait method, which is definitely not a type. -However, the `Age` trait provides an associated type `Empire` which can be -used as a type: - -``` -trait Age { - type Empire; - fn Mythology() {} -} - -impl Age for u8 { - type Empire = u16; -} - -let _: ::Empire; // ok! -``` -"##, - -E0576: r##" -An associated item wasn't found in the given type. - -Erroneous code example: - -```compile_fail,E0576 -trait Hello { - type Who; - - fn hello() -> ::You; // error! -} -``` - -In this example, we tried to use the non-existent associated type `You` of the -`Hello` trait. To fix this error, use an existing associated type: - -``` -trait Hello { - type Who; - - fn hello() -> ::Who; // ok! -} -``` -"##, - E0603: r##" A private item was used outside its scope. @@ -1856,7 +1645,7 @@ An item usage is ambiguous. Erroneous code example: -```compile_fail,edition2018,E0659 +```compile_fail,E0659 pub mod moon { pub fn foo() {} } @@ -1866,12 +1655,12 @@ pub mod earth { } mod collider { - pub use crate::moon::*; - pub use crate::earth::*; + pub use moon::*; + pub use earth::*; } fn main() { - crate::collider::foo(); // ERROR: `foo` is ambiguous + collider::foo(); // ERROR: `foo` is ambiguous } ``` @@ -1883,7 +1672,7 @@ functions collide. To solve this error, the best solution is generally to keep the path before the item when using it. Example: -```edition2018 +``` pub mod moon { pub fn foo() {} } @@ -1893,45 +1682,29 @@ pub mod earth { } mod collider { - pub use crate::moon; - pub use crate::earth; + pub use moon; + pub use earth; } fn main() { - crate::collider::moon::foo(); // ok! - crate::collider::earth::foo(); // ok! + collider::moon::foo(); // ok! + collider::earth::foo(); // ok! } ``` "##, E0671: r##" -#### Note: this error code is no longer emitted by the compiler. - Const parameters cannot depend on type parameters. The following is therefore invalid: -```compile_fail,E0741 +```compile_fail,E0671 #![feature(const_generics)] -fn const_id() -> T { // error +fn const_id() -> T { // error: const parameter + // depends on type parameter N } ``` "##, - -E0735: r##" -Type parameter defaults cannot use `Self` on structs, enums, or unions. - -Erroneous code example: - -```compile_fail,E0735 -struct Foo> { - field1: Option, - field2: Option, -} -// error: type parameters cannot use `Self` in their defaults. -``` -"##, - ; // E0153, unused error code // E0157, unused error code @@ -1950,6 +1723,10 @@ struct Foo> { // E0427, merged into 530 // E0467, removed // E0470, removed + E0573, + E0574, + E0575, + E0576, E0577, E0578, } diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 136ab1f0444fa..33a85c6c77026 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -5,6 +5,7 @@ //! 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}; @@ -45,6 +46,16 @@ struct BindingInfo { binding_mode: BindingMode, } +#[derive(Copy, Clone)] +enum GenericParameters<'a, 'b> { + NoGenericParams, + HasGenericParams(// Type parameters. + &'b Generics, + + // The kind of the rib used for type parameters. + RibKind<'a>), +} + #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum PatternSource { Match, @@ -74,10 +85,6 @@ enum PatBoundCtx { Or, } -/// Does this the item (from the item rib scope) allow generic parameters? -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -crate enum HasGenericParams { Yes, No } - /// The rib kind restricts certain accesses, /// e.g. to a `Res::Local` of an outer item. #[derive(Copy, Clone, Debug)] @@ -96,7 +103,7 @@ crate enum RibKind<'a> { FnItemRibKind, /// We passed through an item scope. Disallow upvars. - ItemRibKind(HasGenericParams), + ItemRibKind, /// We're in a constant item. Can't refer to dynamic stuff. ConstantItemRibKind, @@ -111,6 +118,9 @@ crate enum RibKind<'a> { /// from the default of a type parameter because they're not declared /// before said type parameter. Also see the `visit_generics` override. ForwardTyParamBanRibKind, + + /// We forbid the use of type parameters as the types of const parameters. + TyParamAsConstParamTy, } impl RibKind<'_> { @@ -124,8 +134,9 @@ impl RibKind<'_> { | ModuleRibKind(_) | MacroDefinition(_) => false, AssocItemRibKind - | ItemRibKind(_) - | ForwardTyParamBanRibKind => true, + | ItemRibKind + | ForwardTyParamBanRibKind + | TyParamAsConstParamTy => true, } } } @@ -341,9 +352,6 @@ struct LateResolutionVisitor<'a, 'b> { /// The current self item if inside an ADT (used for better errors). current_self_item: Option, - /// The current enclosing funciton (used for better errors). - current_function: Option, - /// A list of labels as of yet unused. Labels will be removed from this map when /// they are used (in a `break` or `continue` statement) unused_labels: FxHashMap, @@ -398,24 +406,19 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { visit::walk_poly_trait_ref(self, tref, m); } fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) { - match foreign_item.kind { + let generic_params = match foreign_item.kind { ForeignItemKind::Fn(_, ref generics) => { - self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { - visit::walk_foreign_item(this, foreign_item); - }); - } - ForeignItemKind::Static(..) => { - self.with_item_rib(HasGenericParams::No, |this| { - visit::walk_foreign_item(this, foreign_item); - }); + HasGenericParams(generics, ItemRibKind) } - ForeignItemKind::Ty | ForeignItemKind::Macro(..) => { - visit::walk_foreign_item(self, foreign_item); - } - } + ForeignItemKind::Static(..) => NoGenericParams, + ForeignItemKind::Ty => NoGenericParams, + ForeignItemKind::Macro(..) => NoGenericParams, + }; + self.with_generic_param_rib(generic_params, |this| { + visit::walk_foreign_item(this, foreign_item); + }); } - fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, sp: Span, _: NodeId) { - let previous_value = replace(&mut self.current_function, Some(sp)); + fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, _: Span, _: NodeId) { debug!("(resolving function) entering function"); let rib_kind = match fn_kind { FnKind::ItemFn(..) => FnItemRibKind, @@ -441,7 +444,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { debug!("(resolving function) leaving function"); }) }); - self.current_function = previous_value; } fn visit_generics(&mut self, generics: &'tcx Generics) { @@ -466,18 +468,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { } })); - // rust-lang/rust#61631: The type `Self` is essentially - // another type parameter. For ADTs, we consider it - // well-defined only after all of the ADT type parameters have - // been provided. Therefore, we do not allow use of `Self` - // anywhere in ADT type parameter defaults. - // - // (We however cannot ban `Self` for defaults on *all* generic - // lists; e.g. trait generics can usefully refer to `Self`, - // such as in the case of `trait Add`.) - if self.current_self_item.is_some() { // (`Some` if + only if we are in ADT's generics.) - default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); - } + // We also ban access to type parameters for use as the types of const parameters. + let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy); + const_ty_param_ban_rib.bindings.extend(generics.params.iter() + .filter(|param| { + if let GenericParamKind::Type { .. } = param.kind { + true + } else { + false + } + }) + .map(|param| (Ident::with_dummy_span(param.ident.name), Res::Err))); for param in &generics.params { match param.kind { @@ -497,10 +498,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { 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); + for bound in ¶m.bounds { self.visit_param_bound(bound); } + self.visit_ty(ty); + + const_ty_param_ban_rib = self.ribs[TypeNS].pop().unwrap(); } } } @@ -530,7 +536,6 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { current_trait_assoc_types: Vec::new(), current_self_type: None, current_self_item: None, - current_function: None, unused_labels: Default::default(), current_type_ascription: Vec::new(), } @@ -642,7 +647,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { fn resolve_adt(&mut self, item: &Item, generics: &Generics) { debug!("resolve_adt"); self.with_current_self_item(item, |this| { - this.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { + this.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| { let item_def_id = this.r.definitions.local_def_id(item.id); this.with_self_rib(Res::SelfTy(None, Some(item_def_id)), |this| { visit::walk_item(this, item); @@ -701,8 +706,10 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { ItemKind::TyAlias(_, ref generics) | ItemKind::OpaqueTy(_, ref generics) | ItemKind::Fn(_, _, ref generics, _) => { - self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), - |this| visit::walk_item(this, item)); + self.with_generic_param_rib( + HasGenericParams(generics, ItemRibKind), + |this| visit::walk_item(this, item) + ); } ItemKind::Enum(_, ref generics) | @@ -720,7 +727,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => { // Create a new rib for the trait-wide type parameters. - self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { + self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| { let local_def_id = this.r.definitions.local_def_id(item.id); this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| { this.visit_generics(generics); @@ -728,32 +735,35 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { for trait_item in trait_items { this.with_trait_items(trait_items, |this| { - this.with_generic_param_rib(&trait_item.generics, AssocItemRibKind, - |this| { - match trait_item.kind { - TraitItemKind::Const(ref ty, ref default) => { - this.visit_ty(ty); - - // Only impose the restrictions of - // ConstRibKind for an actual constant - // expression in a provided default. - if let Some(ref expr) = *default{ - this.with_constant_rib(|this| { - this.visit_expr(expr); - }); - } - } - TraitItemKind::Method(_, _) => { - visit::walk_trait_item(this, trait_item) - } - TraitItemKind::Type(..) => { - visit::walk_trait_item(this, trait_item) - } - TraitItemKind::Macro(_) => { - panic!("unexpanded macro in resolve!") + let generic_params = HasGenericParams( + &trait_item.generics, + AssocItemRibKind, + ); + this.with_generic_param_rib(generic_params, |this| { + match trait_item.kind { + TraitItemKind::Const(ref ty, ref default) => { + this.visit_ty(ty); + + // Only impose the restrictions of + // ConstRibKind for an actual constant + // expression in a provided default. + if let Some(ref expr) = *default{ + this.with_constant_rib(|this| { + this.visit_expr(expr); + }); } - }; - }); + } + TraitItemKind::Method(_, _) => { + visit::walk_trait_item(this, trait_item) + } + TraitItemKind::Type(..) => { + visit::walk_trait_item(this, trait_item) + } + TraitItemKind::Macro(_) => { + panic!("unexpanded macro in resolve!") + } + }; + }); }); } }); @@ -762,7 +772,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { ItemKind::TraitAlias(ref generics, ref bounds) => { // Create a new rib for the trait-wide type parameters. - self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { + self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| { let local_def_id = this.r.definitions.local_def_id(item.id); this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| { this.visit_generics(generics); @@ -780,7 +790,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(ref ty, ref expr) => { debug!("resolve_item ItemKind::Const"); - self.with_item_rib(HasGenericParams::No, |this| { + self.with_item_rib(|this| { this.visit_ty(ty); this.with_constant_rib(|this| { this.visit_expr(expr); @@ -801,75 +811,91 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } } - fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: RibKind<'a>, f: F) + fn with_generic_param_rib<'c, F>(&'c mut self, generic_params: GenericParameters<'a, 'c>, f: F) where F: FnOnce(&mut Self) { debug!("with_generic_param_rib"); - let mut function_type_rib = Rib::new(kind); - let mut function_value_rib = Rib::new(kind); - let mut seen_bindings = FxHashMap::default(); - - // We also can't shadow bindings from the parent item - if let AssocItemRibKind = kind { - let mut add_bindings_for_ns = |ns| { - let parent_rib = self.ribs[ns].iter() - .rfind(|r| if let ItemRibKind(_) = r.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 { - if let GenericParamKind::Lifetime { .. } = param.kind { - continue; - } - - let def_kind = match param.kind { - GenericParamKind::Type { .. } => DefKind::TyParam, - GenericParamKind::Const { .. } => DefKind::ConstParam, - _ => unreachable!(), - }; - - let ident = param.ident.modern(); - debug!("with_generic_param_rib: {}", param.id); - - if seen_bindings.contains_key(&ident) { - let span = seen_bindings.get(&ident).unwrap(); - let err = ResolutionError::NameAlreadyUsedInParameterList( - ident.name, - *span, - ); - self.r.report_error(param.ident.span, err); - } - seen_bindings.entry(ident).or_insert(param.ident.span); - - // Plain insert (no renaming). - let res = Res::Def(def_kind, self.r.definitions.local_def_id(param.id)); - - match param.kind { - GenericParamKind::Type { .. } => { - function_type_rib.bindings.insert(ident, res); - self.r.record_partial_res(param.id, PartialRes::new(res)); + match generic_params { + HasGenericParams(generics, rib_kind) => { + 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); } - GenericParamKind::Const { .. } => { - function_value_rib.bindings.insert(ident, res); - self.r.record_partial_res(param.id, PartialRes::new(res)); + for param in &generics.params { + match param.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { .. } => { + let ident = param.ident.modern(); + debug!("with_generic_param_rib: {}", param.id); + + if seen_bindings.contains_key(&ident) { + let span = seen_bindings.get(&ident).unwrap(); + let err = ResolutionError::NameAlreadyUsedInParameterList( + ident.name, + *span, + ); + self.r.report_error(param.ident.span, err); + } + seen_bindings.entry(ident).or_insert(param.ident.span); + + // Plain insert (no renaming). + let res = Res::Def( + DefKind::TyParam, + self.r.definitions.local_def_id(param.id), + ); + function_type_rib.bindings.insert(ident, res); + self.r.record_partial_res(param.id, PartialRes::new(res)); + } + GenericParamKind::Const { .. } => { + let ident = param.ident.modern(); + debug!("with_generic_param_rib: {}", param.id); + + if seen_bindings.contains_key(&ident) { + let span = seen_bindings.get(&ident).unwrap(); + let err = ResolutionError::NameAlreadyUsedInParameterList( + ident.name, + *span, + ); + self.r.report_error(param.ident.span, err); + } + seen_bindings.entry(ident).or_insert(param.ident.span); + + let res = Res::Def( + DefKind::ConstParam, + self.r.definitions.local_def_id(param.id), + ); + function_value_rib.bindings.insert(ident, res); + self.r.record_partial_res(param.id, PartialRes::new(res)); + } + } } - _ => unreachable!(), + self.ribs[ValueNS].push(function_value_rib); + self.ribs[TypeNS].push(function_type_rib); } - } - self.ribs[ValueNS].push(function_value_rib); - self.ribs[TypeNS].push(function_type_rib); + NoGenericParams => { + // Nothing to do. + } + } f(self); - self.ribs[TypeNS].pop(); - self.ribs[ValueNS].pop(); + if let HasGenericParams(..) = generic_params { + self.ribs[TypeNS].pop(); + self.ribs[ValueNS].pop(); + } } fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) { @@ -878,9 +904,8 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { self.label_ribs.pop(); } - fn with_item_rib(&mut self, has_generic_params: HasGenericParams, f: impl FnOnce(&mut Self)) { - let kind = ItemRibKind(has_generic_params); - self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f)) + 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: impl FnOnce(&mut Self)) { @@ -985,7 +1010,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { impl_items: &[ImplItem]) { debug!("resolve_implementation"); // If applicable, create a rib for the type parameters. - self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { + self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| { // Dummy self type for better errors if `Self` is used in the trait path. this.with_self_rib(Res::SelfTy(None, None), |this| { // Resolve the trait reference, if necessary. @@ -1006,9 +1031,9 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { 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. - this.with_generic_param_rib(&impl_item.generics, - AssocItemRibKind, - |this| { + let generic_params = HasGenericParams(&impl_item.generics, + AssocItemRibKind); + this.with_generic_param_rib(generic_params, |this| { use crate::ResolutionError::*; match impl_item.kind { ImplItemKind::Const(..) => { diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 2721df4c68763..0d35cc53ac6f3 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -13,7 +13,7 @@ use rustc::hir::PrimTy; use rustc::session::config::nightly_options; use rustc::util::nodemap::FxHashSet; use syntax::ast::{self, Expr, ExprKind, Ident, NodeId, Path, Ty, TyKind}; -use syntax_expand::base::MacroKind; +use syntax::ext::base::MacroKind; use syntax::symbol::kw; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::Span; @@ -115,10 +115,8 @@ impl<'a> LateResolutionVisitor<'a, '_> { if is_self_type(path, ns) { syntax::diagnostic_used!(E0411); err.code(DiagnosticId::Error("E0411".into())); - err.span_label( - span, - format!("`Self` is only available in impls, traits, and type definitions"), - ); + err.span_label(span, format!("`Self` is only available in impls, traits, \ + and type definitions")); return (err, Vec::new()); } if is_self_value(path, ns) { @@ -127,16 +125,17 @@ impl<'a> LateResolutionVisitor<'a, '_> { syntax::diagnostic_used!(E0424); err.code(DiagnosticId::Error("E0424".into())); err.span_label(span, match source { - PathSource::Pat => format!( - "`self` value is a keyword and may not be bound to variables or shadowed", - ), - _ => format!( - "`self` value is a keyword only available in methods with a `self` parameter", - ), + PathSource::Pat => { + format!("`self` value is a keyword \ + and may not be bound to \ + variables or shadowed") + } + _ => { + format!("`self` value is a keyword \ + only available in methods \ + with `self` parameter") + } }); - if let Some(span) = &self.current_function { - err.span_label(*span, "this function doesn't have a `self` parameter"); - } return (err, Vec::new()); } @@ -349,7 +348,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { _ => false, }; - let mut bad_struct_syntax_suggestion = |def_id: DefId| { + let mut bad_struct_syntax_suggestion = || { let (followed_by_brace, closing_brace) = self.followed_by_brace(span); let mut suggested = false; match source { @@ -375,9 +374,6 @@ impl<'a> LateResolutionVisitor<'a, '_> { _ => {} } if !suggested { - if let Some(span) = self.r.definitions.opt_span(def_id) { - err.span_label(span, &format!("`{}` defined here", path_str)); - } err.span_label( span, format!("did you mean `{} {{ /* fields */ }}`?", path_str), @@ -441,21 +437,18 @@ impl<'a> LateResolutionVisitor<'a, '_> { ); } } else { - bad_struct_syntax_suggestion(def_id); + bad_struct_syntax_suggestion(); } } - (Res::Def(DefKind::Union, def_id), _) | - (Res::Def(DefKind::Variant, def_id), _) | - (Res::Def(DefKind::Ctor(_, CtorKind::Fictive), def_id), _) if ns == ValueNS => { - bad_struct_syntax_suggestion(def_id); + (Res::Def(DefKind::Union, _), _) | + (Res::Def(DefKind::Variant, _), _) | + (Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _), _) if ns == ValueNS => { + bad_struct_syntax_suggestion(); } - (Res::Def(DefKind::Ctor(_, CtorKind::Fn), def_id), _) if ns == ValueNS => { - if let Some(span) = self.r.definitions.opt_span(def_id) { - err.span_label(span, &format!("`{}` defined here", path_str)); - } + (Res::Def(DefKind::Ctor(_, CtorKind::Fn), _), _) if ns == ValueNS => { err.span_label( span, - format!("did you mean `{}( /* fields */ )`?", path_str), + format!("did you mean `{} ( /* fields */ )`?", path_str), ); } (Res::SelfTy(..), _) if ns == ValueNS => { @@ -498,8 +491,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { Res::Def(DefKind::Struct, did) | Res::Def(DefKind::Union, did) if resolution.unresolved_segments() == 0 => { if let Some(field_names) = self.r.field_names.get(&did) { - if field_names.iter() - .any(|&field_name| ident.name == field_name.node) { + if field_names.iter().any(|&field_name| ident.name == field_name) { return Some(AssocSuggestion::Field); } } @@ -730,7 +722,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { // abort if the module is already found if result.is_some() { break; } - in_module.for_each_child(self.r, |_, ident, _, name_binding| { + in_module.for_each_child_stable(self.r, |_, ident, _, name_binding| { // abort if the module is already found or if name_binding is private external if result.is_some() || !name_binding.vis.is_visible_locally() { return @@ -762,7 +754,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { fn collect_enum_variants(&mut self, def_id: DefId) -> Option> { self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| { let mut variants = Vec::new(); - enum_module.for_each_child(self.r, |_, ident, _, name_binding| { + enum_module.for_each_child_stable(self.r, |_, ident, _, name_binding| { if let Res::Def(DefKind::Variant, _) = name_binding.res() { let mut segms = enum_import_suggestion.path.segments.clone(); segms.push(ast::PathSegment::from_ident(ident)); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 9239280634724..bf86a37433840 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -9,8 +9,10 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(inner_deref)] #![feature(crate_visibility_modifier)] #![feature(label_break_value)] +#![feature(mem_take)] #![feature(nll)] #![recursion_limit="256"] @@ -21,30 +23,30 @@ use Determinacy::*; use rustc::hir::map::Definitions; use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str}; -use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn}; +use rustc::middle::cstore::CrateStore; use rustc::session::Session; use rustc::lint; use rustc::hir::def::{self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrKind, ExportMap}; use rustc::hir::def::Namespace::*; -use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId}; +use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::hir::{TraitMap, GlobMap}; -use rustc::ty::{self, DefIdTree, ResolverOutputs}; +use rustc::ty; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; use rustc::span_bug; use rustc_metadata::creader::CrateLoader; use rustc_metadata::cstore::CStore; -use syntax_expand::hygiene::{ExpnId, Transparency, SyntaxContext}; -use syntax_expand::base::{SyntaxExtension, MacroKind, SpecialDerives}; -use syntax::{struct_span_err, unwrap_or}; -use syntax::attr; +use syntax::ext::hygiene::{ExpnId, Transparency, SyntaxContext}; use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; -use syntax::ast::{ItemKind, Path, CRATE_NODE_ID, Crate}; -use syntax::print::pprust; +use syntax::ext::base::{SyntaxExtension, MacroKind, SpecialDerives}; use syntax::symbol::{kw, sym}; -use syntax::source_map::Spanned; + use syntax::visit::{self, Visitor}; +use syntax::attr; +use syntax::ast::{CRATE_NODE_ID, Crate}; +use syntax::ast::{ItemKind, Path}; +use syntax::{struct_span_err, unwrap_or}; use syntax_pos::{Span, DUMMY_SP}; use errors::{Applicability, DiagnosticBuilder}; @@ -56,11 +58,10 @@ use std::{cmp, fmt, iter, ptr}; use std::collections::BTreeSet; use rustc_data_structures::ptr_key::PtrKey; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::fx::FxIndexMap; use diagnostics::{Suggestion, ImportSuggestion}; use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding}; -use late::{HasGenericParams, PathSource, Rib, RibKind::*}; +use late::{PathSource, Rib, RibKind::*}; use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; use macros::{LegacyBinding, LegacyScope}; @@ -177,7 +178,7 @@ impl Ord for BindingError { enum ResolutionError<'a> { /// Error E0401: can't use type or const parameters from outer function. - GenericParamsFromOuterFunction(Res, HasGenericParams), + GenericParamsFromOuterFunction(Res), /// Error E0403: the name is already used for a type or const parameter in this generic /// parameter list. NameAlreadyUsedInParameterList(Name, Span), @@ -213,8 +214,8 @@ enum ResolutionError<'a> { BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>), /// Error E0128: type parameters with a default cannot use forward-declared identifiers. ForwardDeclaredTyParam, // FIXME(const_generics:defaults) - /// Error E0735: type parameters with a default cannot use `Self` - SelfInTyParamDefault, + /// Error E0671: const parameter cannot depend on type parameter. + ConstParamDependentOnTypeParam, } // A minimal representation of a path segment. We use this in resolve because @@ -428,22 +429,7 @@ impl ModuleKind { } } -/// A key that identifies a binding in a given `Module`. -/// -/// Multiple bindings in the same module can have the same key (in a valid -/// program) if all but one of them come from glob imports. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -struct BindingKey { - /// The identifier for the binding, aways the `modern` version of the - /// identifier. - ident: Ident, - ns: Namespace, - /// 0 if ident is not `_`, otherwise a value that's unique to the specific - /// `_` in the expanded AST that introduced this binding. - disambiguator: u32, -} - -type Resolutions<'a> = RefCell>>>; +type Resolutions<'a> = RefCell>>>; /// One node in the tree of modules. pub struct ModuleData<'a> { @@ -503,8 +489,19 @@ impl<'a> ModuleData<'a> { fn for_each_child(&'a self, resolver: &mut R, mut f: F) where R: AsMut>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>) { - for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() { - name_resolution.borrow().binding.map(|binding| f(resolver, key.ident, key.ns, binding)); + for (&(ident, ns), name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() { + name_resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding)); + } + } + + fn for_each_child_stable(&'a self, resolver: &mut R, mut f: F) + where R: AsMut>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>) + { + let resolutions = resolver.as_mut().resolutions(self).borrow(); + let mut resolutions = resolutions.iter().collect::>(); + resolutions.sort_by_cached_key(|&(&(ident, ns), _)| (ident.as_str(), ns)); + for &(&(ident, ns), &resolution) in resolutions.iter() { + resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding)); } } @@ -827,20 +824,21 @@ pub struct ExternPreludeEntry<'a> { /// This is the visitor that walks the whole crate. pub struct Resolver<'a> { session: &'a Session, + cstore: &'a CStore, - definitions: Definitions, + pub definitions: Definitions, - graph_root: Module<'a>, + pub graph_root: Module<'a>, prelude: Option>, - extern_prelude: FxHashMap>, + pub extern_prelude: FxHashMap>, /// N.B., this is used only for better diagnostics, not name resolution itself. has_self: FxHashSet, /// Names of fields of an item `DefId` accessible with dot syntax. /// Used for hints during error reporting. - field_names: FxHashMap>>, + field_names: FxHashMap>, /// All imports known to succeed or fail. determined_imports: Vec<&'a ImportDirective<'a>>, @@ -865,10 +863,8 @@ pub struct Resolver<'a> { /// Resolutions for labels (node IDs of their corresponding blocks or loops). label_res_map: NodeMap, - /// `CrateNum` resolutions of `extern crate` items. - extern_crate_map: NodeMap, - export_map: ExportMap, - trait_map: TraitMap, + pub export_map: ExportMap, + pub trait_map: TraitMap, /// A map from nodes to anonymous modules. /// Anonymous modules are pseudo-modules that are implicitly created around items @@ -890,16 +886,15 @@ pub struct Resolver<'a> { /// language items. empty_module: Module<'a>, module_map: FxHashMap>, - extern_module_map: FxHashMap>, + extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>, binding_parent_modules: FxHashMap>, Module<'a>>, - underscore_disambiguator: u32, /// Maps glob imports to the names of items actually imported. - glob_map: GlobMap, + pub glob_map: GlobMap, used_imports: FxHashSet<(NodeId, Namespace)>, - maybe_unused_trait_imports: NodeSet, - maybe_unused_extern_crates: Vec<(NodeId, Span)>, + pub maybe_unused_trait_imports: NodeSet, + pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, /// Privacy errors are delayed until the end in order to deduplicate them. privacy_errors: Vec>, @@ -913,11 +908,11 @@ pub struct Resolver<'a> { arenas: &'a ResolverArenas<'a>, dummy_binding: &'a NameBinding<'a>, - crate_loader: CrateLoader<'a>, + crate_loader: &'a mut CrateLoader<'a>, macro_names: FxHashSet, builtin_macros: FxHashMap, macro_use_prelude: FxHashMap>, - all_macros: FxHashMap, + pub all_macros: FxHashMap, macro_map: FxHashMap>, dummy_ext_bang: Lrc, dummy_ext_derive: Lrc, @@ -1008,11 +1003,11 @@ impl<'a> AsMut> for Resolver<'a> { fn as_mut(&mut self) -> &mut Resolver<'a> { self } } -impl<'a, 'b> DefIdTree for &'a Resolver<'b> { +impl<'a, 'b> ty::DefIdTree for &'a Resolver<'b> { fn parent(self, id: DefId) -> Option { match id.krate { LOCAL_CRATE => self.definitions.def_key(id.index).parent, - _ => self.cstore().def_key(id).parent, + _ => self.cstore.def_key(id).parent, }.map(|index| DefId { index, ..id }) } } @@ -1020,10 +1015,6 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> { /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that /// the resolver is no longer needed as all the relevant information is inline. impl<'a> hir::lowering::Resolver for Resolver<'a> { - fn cstore(&self) -> &dyn CrateStore { - self.cstore() - } - fn resolve_str_path( &mut self, span: Span, @@ -1084,9 +1075,10 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { impl<'a> Resolver<'a> { pub fn new(session: &'a Session, + cstore: &'a CStore, krate: &Crate, crate_name: &str, - metadata_loader: &'a MetadataLoaderDyn, + crate_loader: &'a mut CrateLoader<'a>, arenas: &'a ResolverArenas<'a>) -> Resolver<'a> { let root_def_id = DefId::local(CRATE_DEF_INDEX); @@ -1147,6 +1139,8 @@ impl<'a> Resolver<'a> { Resolver { session, + cstore, + definitions, // The outermost module has def ID 0; this is not reflected in the @@ -1169,10 +1163,8 @@ impl<'a> Resolver<'a> { partial_res_map: Default::default(), import_res_map: Default::default(), label_res_map: Default::default(), - extern_crate_map: Default::default(), export_map: FxHashMap::default(), trait_map: Default::default(), - underscore_disambiguator: 0, empty_module, module_map, block_map: Default::default(), @@ -1200,7 +1192,7 @@ impl<'a> Resolver<'a> { vis: ty::Visibility::Public, }), - crate_loader: CrateLoader::new(session, metadata_loader, crate_name), + crate_loader, macro_names: FxHashSet::default(), builtin_macros: Default::default(), macro_use_prelude: FxHashMap::default(), @@ -1234,42 +1226,6 @@ impl<'a> Resolver<'a> { Default::default() } - pub fn into_outputs(self) -> ResolverOutputs { - ResolverOutputs { - definitions: self.definitions, - cstore: Box::new(self.crate_loader.into_cstore()), - extern_crate_map: self.extern_crate_map, - export_map: self.export_map, - trait_map: self.trait_map, - glob_map: self.glob_map, - maybe_unused_trait_imports: self.maybe_unused_trait_imports, - maybe_unused_extern_crates: self.maybe_unused_extern_crates, - extern_prelude: self.extern_prelude.iter().map(|(ident, entry)| { - (ident.name, entry.introduced_by_item) - }).collect(), - } - } - - pub fn clone_outputs(&self) -> ResolverOutputs { - ResolverOutputs { - definitions: self.definitions.clone(), - cstore: Box::new(self.cstore().clone()), - extern_crate_map: self.extern_crate_map.clone(), - export_map: self.export_map.clone(), - trait_map: self.trait_map.clone(), - glob_map: self.glob_map.clone(), - maybe_unused_trait_imports: self.maybe_unused_trait_imports.clone(), - maybe_unused_extern_crates: self.maybe_unused_extern_crates.clone(), - extern_prelude: self.extern_prelude.iter().map(|(ident, entry)| { - (ident.name, entry.introduced_by_item) - }).collect(), - } - } - - pub fn cstore(&self) -> &CStore { - self.crate_loader.cstore() - } - fn non_macro_attr(&self, mark_used: bool) -> Lrc { self.non_macro_attrs[mark_used as usize].clone() } @@ -1308,9 +1264,6 @@ impl<'a> Resolver<'a> { /// Entry point to crate resolution. pub fn resolve_crate(&mut self, krate: &Crate) { - let _prof_timer = - self.session.prof.generic_activity("resolve_crate"); - ImportResolver { r: self }.finalize_imports(); self.finalize_macro_resolutions(); @@ -1333,17 +1286,6 @@ impl<'a> Resolver<'a> { self.arenas.alloc_module(module) } - fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey { - let ident = ident.modern(); - let disambiguator = if ident.name == kw::Underscore { - self.underscore_disambiguator += 1; - self.underscore_disambiguator - } else { - 0 - }; - BindingKey { ident, ns, disambiguator } - } - fn resolutions(&mut self, module: Module<'a>) -> &'a Resolutions<'a> { if module.populate_on_access.get() { module.populate_on_access.set(false); @@ -1352,9 +1294,9 @@ impl<'a> Resolver<'a> { &module.lazy_resolutions } - fn resolution(&mut self, module: Module<'a>, key: BindingKey) + fn resolution(&mut self, module: Module<'a>, ident: Ident, ns: Namespace) -> &'a RefCell> { - *self.resolutions(module).borrow_mut().entry(key) + *self.resolutions(module).borrow_mut().entry((ident.modern(), ns)) .or_insert_with(|| self.arenas.alloc_name_resolution()) } @@ -1594,7 +1536,7 @@ impl<'a> Resolver<'a> { if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() { // The ident resolves to a type parameter or local variable. return Some(LexicalScopeBinding::Res( - self.validate_res_from_ribs(i, rib_ident, res, record_used, path_span, ribs), + self.validate_res_from_ribs(i, res, record_used, path_span, ribs), )); } @@ -2075,13 +2017,13 @@ impl<'a> Resolver<'a> { let mut candidates = self.lookup_import_candidates(ident, TypeNS, is_mod); candidates.sort_by_cached_key(|c| { - (c.path.segments.len(), pprust::path_to_string(&c.path)) + (c.path.segments.len(), c.path.to_string()) }); if let Some(candidate) = candidates.get(0) { ( String::from("unresolved import"), Some(( - vec![(ident.span, pprust::path_to_string(&candidate.path))], + vec![(ident.span, candidate.path.to_string())], String::from("a similar path exists"), Applicability::MaybeIncorrect, )), @@ -2180,7 +2122,6 @@ impl<'a> Resolver<'a> { fn validate_res_from_ribs( &mut self, rib_index: usize, - rib_ident: Ident, res: Res, record_used: bool, span: Span, @@ -2192,12 +2133,16 @@ impl<'a> Resolver<'a> { // An invalid forward use of a type parameter from a previous default. if let ForwardTyParamBanRibKind = all_ribs[rib_index].kind { if record_used { - let res_error = if rib_ident.name == kw::SelfUpper { - ResolutionError::SelfInTyParamDefault - } else { - ResolutionError::ForwardDeclaredTyParam - }; - self.report_error(span, res_error); + self.report_error(span, ResolutionError::ForwardDeclaredTyParam); + } + assert_eq!(res, Res::Err); + return Res::Err; + } + + // An invalid use of a type parameter as the type of a const parameter. + if let TyParamAsConstParamTy = all_ribs[rib_index].kind { + if record_used { + self.report_error(span, ResolutionError::ConstParamDependentOnTypeParam); } assert_eq!(res, Res::Err); return Res::Err; @@ -2211,10 +2156,10 @@ impl<'a> Resolver<'a> { for rib in ribs { match rib.kind { NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) | - ForwardTyParamBanRibKind => { + ForwardTyParamBanRibKind | TyParamAsConstParamTy => { // Nothing to do. Continue. } - ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => { + ItemRibKind | FnItemRibKind | AssocItemRibKind => { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. @@ -2242,23 +2187,22 @@ impl<'a> Resolver<'a> { } Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => { for rib in ribs { - let has_generic_params = match rib.kind { + match rib.kind { NormalRibKind | AssocItemRibKind | ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind | - ConstantItemRibKind => { + ConstantItemRibKind | TyParamAsConstParamTy => { // Nothing to do. Continue. - continue; } - // This was an attempt to use a type parameter outside its scope. - ItemRibKind(has_generic_params) => has_generic_params, - FnItemRibKind => HasGenericParams::Yes, - }; - - if record_used { - self.report_error(span, ResolutionError::GenericParamsFromOuterFunction( - res, has_generic_params)); + ItemRibKind | FnItemRibKind => { + // This was an attempt to use a type parameter outside its scope. + if record_used { + self.report_error( + span, ResolutionError::GenericParamsFromOuterFunction(res) + ); + } + return Res::Err; + } } - return Res::Err; } } Res::Def(DefKind::ConstParam, _) => { @@ -2270,18 +2214,15 @@ impl<'a> Resolver<'a> { ribs.next(); } for rib in ribs { - let has_generic_params = match rib.kind { - ItemRibKind(has_generic_params) => has_generic_params, - FnItemRibKind => HasGenericParams::Yes, - _ => continue, - }; - - // This was an attempt to use a const parameter outside its scope. - if record_used { - self.report_error(span, ResolutionError::GenericParamsFromOuterFunction( - res, has_generic_params)); + if let ItemRibKind | FnItemRibKind = rib.kind { + // This was an attempt to use a const parameter outside its scope. + if record_used { + self.report_error( + span, ResolutionError::GenericParamsFromOuterFunction(res) + ); + } + return Res::Err; } - return Res::Err; } } _ => {} @@ -2433,38 +2374,32 @@ impl<'a> Resolver<'a> { let mut reported_spans = FxHashSet::default(); for &PrivacyError(dedup_span, ident, binding) in &self.privacy_errors { if reported_spans.insert(dedup_span) { - let session = &self.session; - let mk_struct_span_error = |is_constructor| { - struct_span_err!( - session, - ident.span, - E0603, - "{}{} `{}` is private", - binding.res().descr(), - if is_constructor { " constructor"} else { "" }, - ident.name, - ) - }; - - let mut err = if let NameBindingKind::Res( - Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id), _ - ) = binding.kind { - let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor"); - if let Some(fields) = self.field_names.get(&def_id) { - let mut err = mk_struct_span_error(true); - let first_field = fields.first().expect("empty field list in the map"); - err.span_label( - fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)), - "a constructor is private if any of the fields is private", - ); - err - } else { - mk_struct_span_error(false) + let mut err = struct_span_err!( + self.session, + ident.span, + E0603, + "{} `{}` is private", + binding.res().descr(), + ident.name, + ); + // FIXME: use the ctor's `def_id` to check wether any of the fields is not visible + match binding.kind { + NameBindingKind::Res(Res::Def(DefKind::Ctor( + CtorOf::Struct, + CtorKind::Fn, + ), _def_id), _) => { + err.note("a tuple struct constructor is private if any of its fields \ + is private"); } - } else { - mk_struct_span_error(false) - }; - + NameBindingKind::Res(Res::Def(DefKind::Ctor( + CtorOf::Variant, + CtorKind::Fn, + ), _def_id), _) => { + err.note("a tuple variant constructor is private if any of its fields \ + is private"); + } + _ => {} + } err.emit(); } } @@ -2833,16 +2768,6 @@ impl<'a> Resolver<'a> { seg.id = self.session.next_node_id(); seg } - - // For rustdoc. - pub fn graph_root(&self) -> Module<'a> { - self.graph_root - } - - // For rustdoc. - pub fn all_macros(&self) -> &FxHashMap { - &self.all_macros - } } fn names_to_string(names: &[Name]) -> String { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 94fe0cc57403e..73ad0670659b5 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -14,14 +14,13 @@ use rustc::{ty, lint, span_bug}; use syntax::ast::{self, NodeId, Ident}; use syntax::attr::StabilityLevel; use syntax::edition::Edition; -use syntax_expand::base::{self, InvocationRes, Indeterminate, SpecialDerives}; -use syntax_expand::base::{MacroKind, SyntaxExtension}; -use syntax_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind}; -use syntax_expand::hygiene::{self, ExpnId, ExpnData, ExpnKind}; -use syntax_expand::compile_declarative_macro; +use syntax::ext::base::{self, InvocationRes, Indeterminate, SpecialDerives}; +use syntax::ext::base::{MacroKind, SyntaxExtension}; +use syntax::ext::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind}; +use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind}; +use syntax::ext::compile_declarative_macro; use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name}; use syntax::feature_gate::GateIssue; -use syntax::print::pprust; use syntax::symbol::{Symbol, kw, sym}; use syntax_pos::{Span, DUMMY_SP}; @@ -108,11 +107,15 @@ impl<'a> base::Resolver for Resolver<'a> { }); } - fn visit_ast_fragment_with_placeholders(&mut self, expansion: ExpnId, fragment: &AstFragment) { + // FIXME: `extra_placeholders` should be included into the `fragment` as regular placeholders. + fn visit_ast_fragment_with_placeholders( + &mut self, expansion: ExpnId, fragment: &AstFragment, extra_placeholders: &[NodeId] + ) { // Integrate the new AST fragment into all the definition and module structures. // We are inside the `expansion` now, but other parent scope components are still the same. let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] }; - let output_legacy_scope = self.build_reduced_graph(fragment, parent_scope); + let output_legacy_scope = + self.build_reduced_graph(fragment, extra_placeholders, parent_scope); self.output_legacy_scopes.insert(expansion, output_legacy_scope); parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion); @@ -321,8 +324,7 @@ impl<'a> Resolver<'a> { Ok(if ext.macro_kind() != kind { let expected = kind.descr_expected(); - let path_str = pprust::path_to_string(path); - let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str); + let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path); self.session.struct_span_err(path.span, &msg) .span_label(path.span, format!("not {} {}", kind.article(), expected)) .emit(); @@ -771,6 +773,7 @@ impl<'a> Resolver<'a> { check_consistency(self, &[seg], ident.span, kind, initial_res, res); } Err(..) => { + assert!(initial_binding.is_none()); let expected = kind.descr_expected(); let msg = format!("cannot find {} `{}` in this scope", expected, ident); let mut err = self.session.struct_span_err(ident.span, &msg); @@ -794,25 +797,18 @@ impl<'a> Resolver<'a> { if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level { let feature = stability.feature; if !self.active_features.contains(&feature) && !span.allows_unstable(feature) { - let node_id = ast::CRATE_NODE_ID; - let soft_handler = - |lint, span, msg: &_| self.session.buffer_lint(lint, node_id, span, msg); - stability::report_unstable( - self.session, feature, reason, issue, is_soft, span, soft_handler - ); + stability::report_unstable(self.session, feature, reason, issue, is_soft, span); } } if let Some(depr) = &stability.rustc_depr { - let path = pprust::path_to_string(path); - let (message, lint) = stability::rustc_deprecation_message(depr, &path); + let (message, lint) = stability::rustc_deprecation_message(depr, &path.to_string()); stability::early_report_deprecation( self.session, &message, depr.suggestion, lint, span ); } } if let Some(depr) = &ext.deprecation { - let path = pprust::path_to_string(&path); - let (message, lint) = stability::deprecation_message(depr, &path); + let (message, lint) = stability::deprecation_message(depr, &path.to_string()); stability::early_report_deprecation(self.session, &message, None, lint, span); } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 31340ddd68372..360343169bc3d 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -7,7 +7,7 @@ use crate::{CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, ParentScope use crate::Determinacy::{self, *}; use crate::Namespace::{self, TypeNS, MacroNS}; use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; -use crate::{Resolver, ResolutionError, BindingKey, Segment, ModuleKind}; +use crate::{Resolver, ResolutionError, Segment, ModuleKind}; use crate::{names_to_string, module_to_string}; use crate::diagnostics::Suggestion; @@ -28,7 +28,7 @@ use rustc::util::nodemap::FxHashSet; use rustc::{bug, span_bug}; use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID}; -use syntax_expand::hygiene::ExpnId; +use syntax::ext::hygiene::ExpnId; use syntax::symbol::kw; use syntax::util::lev_distance::find_best_match_for_name; use syntax::{struct_span_err, unwrap_or}; @@ -235,8 +235,7 @@ impl<'a> Resolver<'a> { } }; - let key = self.new_key(ident, ns); - let resolution = self.resolution(module, key) + let resolution = self.resolution(module, ident, ns) .try_borrow_mut() .map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports. @@ -448,16 +447,17 @@ impl<'a> Resolver<'a> { } // Define the name or return the existing binding if there is a collision. - crate fn try_define( + pub fn try_define( &mut self, module: Module<'a>, - key: BindingKey, + ident: Ident, + ns: Namespace, binding: &'a NameBinding<'a>, ) -> Result<(), &'a NameBinding<'a>> { let res = binding.res(); - self.check_reserved_macro_name(key.ident, res); + self.check_reserved_macro_name(ident, res); self.set_binding_parent_module(binding, module); - self.update_resolution(module, key, |this, resolution| { + self.update_resolution(module, ident, ns, |this, resolution| { if let Some(old_binding) = resolution.binding { if res == Res::Err { // Do not override real bindings with `Res::Err`s from error recovery. @@ -479,9 +479,8 @@ impl<'a> Resolver<'a> { } else { (binding, old_binding) }; - if glob_binding.res() != nonglob_binding.res() - && key.ns == MacroNS && nonglob_binding.expansion != ExpnId::root() - { + if glob_binding.res() != nonglob_binding.res() && + ns == MacroNS && nonglob_binding.expansion != ExpnId::root() { resolution.binding = Some(this.ambiguity( AmbiguityKind::GlobVsExpanded, nonglob_binding, @@ -500,9 +499,9 @@ impl<'a> Resolver<'a> { DUPLICATE_MACRO_EXPORTS, CRATE_NODE_ID, binding.span, - &format!("a macro named `{}` has already been exported", key.ident), + &format!("a macro named `{}` has already been exported", ident), BuiltinLintDiagnostics::DuplicatedMacroExports( - key.ident, old_binding.span, binding.span)); + ident, old_binding.span, binding.span)); resolution.binding = Some(binding); } else { @@ -532,9 +531,9 @@ impl<'a> Resolver<'a> { // Use `f` to mutate the resolution of the name in the module. // If the resolution becomes a success, define it in the module's glob importers. fn update_resolution( - &mut self, - module: Module<'a>, - key: BindingKey, + &mut self, module: Module<'a>, + ident: Ident, + ns: Namespace, f: F, ) -> T where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T @@ -542,7 +541,7 @@ impl<'a> Resolver<'a> { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. let (binding, t) = { - let resolution = &mut *self.resolution(module, key).borrow_mut(); + let resolution = &mut *self.resolution(module, ident, ns).borrow_mut(); let old_binding = resolution.binding(); let t = f(self, resolution); @@ -559,7 +558,7 @@ impl<'a> Resolver<'a> { // Define `binding` in `module`s glob importers. for directive in module.glob_importers.borrow_mut().iter() { - let mut ident = key.ident; + let mut ident = ident.modern(); let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) { Some(Some(def)) => self.macro_def_scope(def), Some(None) => directive.parent_scope.module, @@ -567,8 +566,7 @@ impl<'a> Resolver<'a> { }; if self.is_accessible_from(binding.vis, scope) { let imported_binding = self.import(binding, directive); - let key = BindingKey { ident, ..key }; - let _ = self.try_define(directive.parent_scope.module, key, imported_binding); + let _ = self.try_define(directive.parent_scope.module, ident, ns, imported_binding); } } @@ -582,8 +580,7 @@ impl<'a> Resolver<'a> { let dummy_binding = self.dummy_binding; let dummy_binding = self.import(dummy_binding, directive); self.per_ns(|this, ns| { - let key = this.new_key(target, ns); - let _ = this.try_define(directive.parent_scope.module, key, dummy_binding); + let _ = this.try_define(directive.parent_scope.module, target, ns, dummy_binding); // Consider erroneous imports used to avoid duplicate diagnostics. this.record_use(target, ns, dummy_binding, false); }); @@ -673,12 +670,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> { self.throw_unresolved_import_error(errors, None); errors = vec![]; } - if seen_spans.insert(err.span) { + if !seen_spans.contains(&err.span) { let path = import_path_to_string( &import.module_path.iter().map(|seg| seg.ident).collect::>(), &import.subclass, err.span, ); + seen_spans.insert(err.span); errors.push((path, err)); prev_root_id = import.root_id; } @@ -822,11 +820,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let parent = directive.parent_scope.module; match source_bindings[ns].get() { Err(Undetermined) => indeterminate = true, - // Don't update the resolution, because it was never added. - Err(Determined) if target.name == kw::Underscore => {} Err(Determined) => { - let key = this.new_key(target, ns); - this.update_resolution(parent, key, |_, resolution| { + this.update_resolution(parent, target, ns, |_, resolution| { resolution.single_imports.remove(&PtrKey(directive)); }); } @@ -1057,7 +1052,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { _ => None, }; let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter()); - let names = resolutions.filter_map(|(BindingKey { ident: i, .. }, resolution)| { + let names = resolutions.filter_map(|(&(ref i, _), resolution)| { if *i == ident { return None; } // Never suggest the same name match *resolution.borrow() { NameResolution { binding: Some(name_binding), .. } => { @@ -1306,18 +1301,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. - let bindings = self.r.resolutions(module).borrow().iter().filter_map(|(key, resolution)| { - resolution.borrow().binding().map(|binding| (*key, binding)) + let bindings = self.r.resolutions(module).borrow().iter().filter_map(|(ident, resolution)| { + resolution.borrow().binding().map(|binding| (*ident, binding)) }).collect::>(); - for (mut key, binding) in bindings { - let scope = match key.ident.span.reverse_glob_adjust(module.expansion, directive.span) { + for ((mut ident, ns), binding) in bindings { + let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) { Some(Some(def)) => self.r.macro_def_scope(def), Some(None) => directive.parent_scope.module, None => continue, }; if self.r.is_accessible_from(binding.pseudo_vis(), scope) { let imported_binding = self.r.import(binding, directive); - let _ = self.r.try_define(directive.parent_scope.module, key, imported_binding); + let _ = + self.r.try_define(directive.parent_scope.module, ident, ns, imported_binding); } } @@ -1333,23 +1329,29 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut reexports = Vec::new(); - module.for_each_child(self.r, |this, ident, ns, binding| { + for (&(ident, ns), resolution) in self.r.resolutions(module).borrow().iter() { + let resolution = &mut *resolution.borrow_mut(); + let binding = match resolution.binding { + Some(binding) => binding, + None => continue, + }; + // Filter away ambiguous imports and anything that has def-site // hygiene. // FIXME: Implement actual cross-crate hygiene. let is_good_import = binding.is_import() && !binding.is_ambiguity() - && !ident.span.from_expansion(); + && !ident.span.modern().from_expansion(); if is_good_import || binding.is_macro_def() { let res = binding.res(); if res != Res::Err { if let Some(def_id) = res.opt_def_id() { if !def_id.is_local() { - this.cstore().export_macros_untracked(def_id.krate); + self.r.cstore.export_macros_untracked(def_id.krate); } } reexports.push(Export { - ident, - res, + ident: ident.modern(), + res: res, span: binding.span, vis: binding.vis, }); @@ -1358,7 +1360,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind { if ns == TypeNS && orig_binding.is_variant() && - !orig_binding.vis.is_at_least(binding.vis, &*this) { + !orig_binding.vis.is_at_least(binding.vis, &*self) { let msg = match directive.subclass { ImportDirectiveSubclass::SingleImport { .. } => { format!("variant `{}` is private and cannot be re-exported", @@ -1370,34 +1372,33 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let error_id = (DiagnosticMessageId::ErrorId(0), // no code?! Some(binding.span), msg.clone()); - let fresh = this.session.one_time_diagnostics + let fresh = self.r.session.one_time_diagnostics .borrow_mut().insert(error_id); if !fresh { - return; + continue; } msg }, ref s @ _ => bug!("unexpected import subclass {:?}", s) }; - let mut err = this.session.struct_span_err(binding.span, &msg); + let mut err = self.r.session.struct_span_err(binding.span, &msg); let imported_module = match directive.imported_module.get() { Some(ModuleOrUniformRoot::Module(module)) => module, _ => bug!("module should exist"), }; let parent_module = imported_module.parent.expect("parent should exist"); - let resolutions = this.resolutions(parent_module).borrow(); + let resolutions = self.r.resolutions(parent_module).borrow(); let enum_path_segment_index = directive.module_path.len() - 1; let enum_ident = directive.module_path[enum_path_segment_index].ident; - let key = this.new_key(enum_ident, TypeNS); - let enum_resolution = resolutions.get(&key) + let enum_resolution = resolutions.get(&(enum_ident, TypeNS)) .expect("resolution should exist"); let enum_span = enum_resolution.borrow() .binding.expect("binding should exist") .span; - let enum_def_span = this.session.source_map().def_span(enum_span); - let enum_def_snippet = this.session.source_map() + let enum_def_span = self.r.session.source_map().def_span(enum_span); + let enum_def_snippet = self.r.session.source_map() .span_to_snippet(enum_def_span).expect("snippet should exist"); // potentially need to strip extant `crate`/`pub(path)` for suggestion let after_vis_index = enum_def_snippet.find("enum") @@ -1405,7 +1406,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let suggestion = format!("pub {}", &enum_def_snippet[after_vis_index..]); - this.session + self.r.session .diag_span_suggestion_once(&mut err, DiagnosticMessageId::ErrorId(0), enum_def_span, @@ -1414,7 +1415,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { err.emit(); } } - }); + } if reexports.len() > 0 { if let Some(def_id) = module.def_id() { diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index e282936b5d9e7..edd2db3c8f738 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -115,17 +115,15 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { F: FnOnce(&mut Self), { let item_def_id = self.tcx.hir().local_def_id_from_node_id(item_id); - - let tables = if self.tcx.has_typeck_tables(item_def_id) { - self.tcx.typeck_tables_of(item_def_id) + if self.tcx.has_typeck_tables(item_def_id) { + let tables = self.tcx.typeck_tables_of(item_def_id); + let old_tables = self.save_ctxt.tables; + self.save_ctxt.tables = tables; + f(self); + self.save_ctxt.tables = old_tables; } else { - self.save_ctxt.empty_tables - }; - - let old_tables = self.save_ctxt.tables; - self.save_ctxt.tables = tables; - f(self); - self.save_ctxt.tables = old_tables; + f(self); + } } fn span_from_span(&self, span: Span) -> SpanData { @@ -532,14 +530,12 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { ); } - self.nest_tables(item.id, |v| { - for field in def.fields() { - v.process_struct_field_def(field, item.id); - v.visit_ty(&field.ty); - } + for field in def.fields() { + self.process_struct_field_def(field, item.id); + self.visit_ty(&field.ty); + } - v.process_generic_params(ty_params, &qualname, item.id); - }); + self.process_generic_params(ty_params, &qualname, item.id); } fn process_enum( @@ -669,18 +665,15 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { } } } - - let map = &self.tcx.hir(); - self.nest_tables(item.id, |v| { - v.visit_ty(&typ); - if let &Some(ref trait_ref) = trait_ref { - v.process_path(trait_ref.ref_id, &trait_ref.path); - } - v.process_generic_params(generics, "", item.id); - for impl_item in impl_items { - v.process_impl_item(impl_item, map.local_def_id_from_node_id(item.id)); - } - }); + self.visit_ty(&typ); + if let &Some(ref trait_ref) = trait_ref { + self.process_path(trait_ref.ref_id, &trait_ref.path); + } + self.process_generic_params(generics, "", item.id); + for impl_item in impl_items { + let map = &self.tcx.hir(); + self.process_impl_item(impl_item, map.local_def_id_from_node_id(item.id)); + } } fn process_trait( diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 1cfb84bb511e4..e3c898610cde0 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -1,5 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(nll)] +#![feature(inner_deref)] #![recursion_limit="256"] @@ -48,9 +49,6 @@ use log::{debug, error, info}; pub struct SaveContext<'l, 'tcx> { tcx: TyCtxt<'tcx>, tables: &'l ty::TypeckTables<'tcx>, - /// Used as a fallback when nesting the typeck tables during item processing - /// (if these are not available for that item, e.g. don't own a body) - empty_tables: &'l ty::TypeckTables<'tcx>, access_levels: &'l AccessLevels, span_utils: SpanUtils<'tcx>, config: Config, @@ -1117,7 +1115,6 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( let save_ctxt = SaveContext { tcx, tables: &ty::TypeckTables::empty(None), - empty_tables: &ty::TypeckTables::empty(None), access_levels: &access_levels, span_utils: SpanUtils::new(&tcx.sess), config: find_config(config), diff --git a/src/librustc_target/Cargo.toml b/src/librustc_target/Cargo.toml index fba2ea02bb44a..cab1e0e01371d 100644 --- a/src/librustc_target/Cargo.toml +++ b/src/librustc_target/Cargo.toml @@ -14,4 +14,3 @@ log = "0.4" rustc_data_structures = { path = "../librustc_data_structures" } rustc_serialize = { path = "../libserialize", package = "serialize" } syntax_pos = { path = "../libsyntax_pos" } -rustc_index = { path = "../librustc_index" } diff --git a/src/librustc_target/abi/call/asmjs.rs b/src/librustc_target/abi/call/asmjs.rs new file mode 100644 index 0000000000000..92c86372a86f3 --- /dev/null +++ b/src/librustc_target/abi/call/asmjs.rs @@ -0,0 +1,47 @@ +use crate::abi::call::{FnType, ArgType, Uniform}; +use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; + +// Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128 + +// See the https://github.com/kripken/emscripten-fastcomp-clang repository. +// The class `EmscriptenABIInfo` in `/lib/CodeGen/TargetInfo.cpp` contains the ABI definitions. + +fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>) + where Ty: TyLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout +{ + if ret.layout.is_aggregate() { + if let Some(unit) = ret.layout.homogeneous_aggregate(cx).unit() { + let size = ret.layout.size; + if unit.size == size { + ret.cast_to(Uniform { + unit, + total: size + }); + return; + } + } + + ret.make_indirect(); + } +} + +fn classify_arg_ty(arg: &mut ArgType<'_, Ty>) { + if arg.layout.is_aggregate() { + arg.make_indirect_byval(); + } +} + +pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>) + where Ty: TyLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout +{ + if !fty.ret.is_ignore() { + classify_ret_ty(cx, &mut fty.ret); + } + + for arg in &mut fty.args { + if arg.is_ignore() { continue; } + classify_arg_ty(arg); + } +} diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index 17bad189bcfda..fbbd120f934be 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -5,6 +5,7 @@ use crate::spec::{self, HasTargetSpec}; mod aarch64; mod amdgpu; mod arm; +mod asmjs; mod hexagon; mod mips; mod mips64; @@ -21,12 +22,19 @@ mod x86; mod x86_64; mod x86_win64; mod wasm32; -mod wasm32_bindgen_compat; + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum IgnoreMode { + /// C-variadic arguments. + CVarArgs, + /// A zero-sized type. + Zst, +} #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum PassMode { - /// Ignore the argument. - Ignore, + /// Ignore the argument (useful for empty structs and C-variadic args). + Ignore(IgnoreMode), /// Pass the argument directly. Direct(ArgAttributes), /// Pass a pair's elements directly in two arguments. @@ -482,7 +490,7 @@ impl<'a, Ty> ArgType<'a, Ty> { pub fn is_ignore(&self) -> bool { match self.mode { - PassMode::Ignore => true, + PassMode::Ignore(_) => true, _ => false } } @@ -557,6 +565,14 @@ impl<'a, Ty> FnType<'a, Ty> { "powerpc" => powerpc::compute_abi_info(cx, self), "powerpc64" => powerpc64::compute_abi_info(cx, self), "s390x" => s390x::compute_abi_info(cx, self), + "asmjs" => asmjs::compute_abi_info(cx, self), + "wasm32" => { + if cx.target_spec().llvm_target.contains("emscripten") { + asmjs::compute_abi_info(cx, self) + } else { + wasm32::compute_abi_info(self) + } + } "msp430" => msp430::compute_abi_info(self), "sparc" => sparc::compute_abi_info(cx, self), "sparc64" => sparc64::compute_abi_info(cx, self), @@ -565,9 +581,6 @@ impl<'a, Ty> FnType<'a, Ty> { "hexagon" => hexagon::compute_abi_info(self), "riscv32" => riscv::compute_abi_info(self, 32), "riscv64" => riscv::compute_abi_info(self, 64), - "wasm32" if cx.target_spec().target_os != "emscripten" - => wasm32_bindgen_compat::compute_abi_info(self), - "wasm32" | "asmjs" => wasm32::compute_abi_info(cx, self), a => return Err(format!("unrecognized arch \"{}\" in target specification", a)) } diff --git a/src/librustc_target/abi/call/wasm32.rs b/src/librustc_target/abi/call/wasm32.rs index 27799edab9195..1fdcbb8e39bdf 100644 --- a/src/librustc_target/abi/call/wasm32.rs +++ b/src/librustc_target/abi/call/wasm32.rs @@ -1,60 +1,20 @@ -use crate::abi::call::{FnType, ArgType, Uniform}; -use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use crate::abi::call::{FnType, ArgType}; -fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgType<'a, Ty>) -> bool - where Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout -{ - if val.layout.is_aggregate() { - if let Some(unit) = val.layout.homogeneous_aggregate(cx).unit() { - let size = val.layout.size; - if unit.size == size { - val.cast_to(Uniform { - unit, - total: size - }); - return true; - } - } - } - false -} - - -fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>) - where Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout -{ +fn classify_ret_ty(ret: &mut ArgType<'_, Ty>) { ret.extend_integer_width_to(32); - if ret.layout.is_aggregate() { - if !unwrap_trivial_aggregate(cx, ret) { - ret.make_indirect(); - } - } } -fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>) - where Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout -{ +fn classify_arg_ty(arg: &mut ArgType<'_, Ty>) { arg.extend_integer_width_to(32); - if arg.layout.is_aggregate() { - if !unwrap_trivial_aggregate(cx, arg) { - arg.make_indirect_byval(); - } - } } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>) - where Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout -{ +pub fn compute_abi_info(fty: &mut FnType<'_, Ty>) { if !fty.ret.is_ignore() { - classify_ret_ty(cx, &mut fty.ret); + classify_ret_ty(&mut fty.ret); } for arg in &mut fty.args { if arg.is_ignore() { continue; } - classify_arg_ty(cx, arg); + classify_arg_ty(arg); } } diff --git a/src/librustc_target/abi/call/wasm32_bindgen_compat.rs b/src/librustc_target/abi/call/wasm32_bindgen_compat.rs deleted file mode 100644 index 2645e30594cea..0000000000000 --- a/src/librustc_target/abi/call/wasm32_bindgen_compat.rs +++ /dev/null @@ -1,27 +0,0 @@ -// This is not and has never been a correct C ABI for WebAssembly, but -// for a long time this was the C ABI that Rust used. wasm-bindgen -// depends on ABI details for this ABI and is incompatible with the -// correct C ABI, so this ABI is being kept around until wasm-bindgen -// can be fixed to work with the correct ABI. See #63649 for further -// discussion. - -use crate::abi::call::{FnType, ArgType}; - -fn classify_ret_ty(ret: &mut ArgType<'_, Ty>) { - ret.extend_integer_width_to(32); -} - -fn classify_arg_ty(arg: &mut ArgType<'_, Ty>) { - arg.extend_integer_width_to(32); -} - -pub fn compute_abi_info(fty: &mut FnType<'_, Ty>) { - if !fty.ret.is_ignore() { - classify_ret_ty(&mut fty.ret); - } - - for arg in &mut fty.args { - if arg.is_ignore() { continue; } - classify_arg_ty(arg); - } -} diff --git a/src/librustc_target/abi/call/x86.rs b/src/librustc_target/abi/call/x86.rs index 2e809571ab18b..6ca3ce88bd6eb 100644 --- a/src/librustc_target/abi/call/x86.rs +++ b/src/librustc_target/abi/call/x86.rs @@ -88,7 +88,7 @@ pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>, flavor: Fla for arg in &mut fty.args { let attrs = match arg.mode { - PassMode::Ignore | + PassMode::Ignore(_) | PassMode::Indirect(_, None) => continue, PassMode::Direct(ref mut attrs) => attrs, PassMode::Pair(..) | diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index fde5c5bed4d91..dafa866117681 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -6,7 +6,8 @@ use crate::spec::Target; use std::fmt; use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive}; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::newtype_index; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use syntax_pos::symbol::{sym, Symbol}; use syntax_pos::Span; @@ -738,11 +739,7 @@ impl FieldPlacement { pub fn offset(&self, i: usize) -> Size { match *self { - FieldPlacement::Union(count) => { - assert!(i < count, - "Tried to access field {} of union with {} fields", i, count); - Size::ZERO - }, + FieldPlacement::Union(_) => Size::ZERO, FieldPlacement::Array { stride, count } => { let i = i as u64; assert!(i < count); @@ -847,7 +844,7 @@ impl Abi { } } -rustc_index::newtype_index! { +newtype_index! { pub struct VariantIdx { .. } } diff --git a/src/librustc_target/spec/aarch64_unknown_none.rs b/src/librustc_target/spec/aarch64_unknown_none.rs index b9549ec2120dd..8c02bc61088b4 100644 --- a/src/librustc_target/spec/aarch64_unknown_none.rs +++ b/src/librustc_target/spec/aarch64_unknown_none.rs @@ -1,4 +1,4 @@ -// Generic AArch64 target for bare-metal code - Floating point enabled +// Generic AArch64 target for bare-metal code // // Can be used in conjunction with the `target-feature` and // `target-cpu` compiler flags to opt-in more hardware-specific @@ -11,7 +11,7 @@ use super::{LldFlavor, LinkerFlavor, Target, TargetOptions, PanicStrategy}; pub fn target() -> Result { let opts = TargetOptions { linker: Some("rust-lld".to_owned()), - features: "+strict-align,+neon,+fp-armv8".to_string(), + features: "+strict-align".to_string(), executables: true, relocation_model: "static".to_string(), disable_redzone: true, diff --git a/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs b/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs deleted file mode 100644 index b91f2af68ecb8..0000000000000 --- a/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Generic AArch64 target for bare-metal code - Floating point disabled -// -// Can be used in conjunction with the `target-feature` and -// `target-cpu` compiler flags to opt-in more hardware-specific -// features. -// -// For example, `-C target-cpu=cortex-a53`. - -use super::{LldFlavor, LinkerFlavor, Target, TargetOptions, PanicStrategy}; - -pub fn target() -> Result { - let opts = TargetOptions { - linker: Some("rust-lld".to_owned()), - features: "+strict-align,-neon,-fp-armv8".to_string(), - executables: true, - relocation_model: "static".to_string(), - disable_redzone: true, - linker_is_gnu: true, - max_atomic_width: Some(128), - panic_strategy: PanicStrategy::Abort, - abi_blacklist: super::arm_base::abi_blacklist(), - .. Default::default() - }; - Ok(Target { - llvm_target: "aarch64-unknown-none".to_string(), - target_endian: "little".to_string(), - target_pointer_width: "64".to_string(), - target_c_int_width: "32".to_string(), - target_os: "none".to_string(), - target_env: String::new(), - target_vendor: String::new(), - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), - arch: "aarch64".to_string(), - linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), - options: opts, - }) -} diff --git a/src/librustc_target/spec/asmjs_unknown_emscripten.rs b/src/librustc_target/spec/asmjs_unknown_emscripten.rs index e8f9c1f3d61de..6dc140cf160ea 100644 --- a/src/librustc_target/spec/asmjs_unknown_emscripten.rs +++ b/src/librustc_target/spec/asmjs_unknown_emscripten.rs @@ -1,10 +1,40 @@ -use super::{LinkerFlavor, Target, wasm32_unknown_emscripten}; +use super::{LinkArgs, LinkerFlavor, Target, TargetOptions}; pub fn target() -> Result { - let mut target = wasm32_unknown_emscripten::target()?; - target.options.post_link_args - .entry(LinkerFlavor::Em) - .or_default() - .extend(vec!["-s".to_string(), "WASM=0".to_string()]); - Ok(target) + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Em, + vec!["-s".to_string(), + "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(), + "-s".to_string(), + "ABORTING_MALLOC=0".to_string(), + "-s".to_string(), + "WASM=0".to_string()]); + + let opts = TargetOptions { + dynamic_linking: false, + executables: true, + exe_suffix: ".js".to_string(), + linker_is_gnu: true, + allow_asm: false, + obj_is_bitcode: true, + is_like_emscripten: true, + max_atomic_width: Some(32), + post_link_args: args, + target_family: Some("unix".to_string()), + codegen_backend: "emscripten".to_string(), + .. Default::default() + }; + Ok(Target { + llvm_target: "asmjs-unknown-emscripten".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + target_os: "emscripten".to_string(), + target_env: String::new(), + target_vendor: "unknown".to_string(), + data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(), + arch: "asmjs".to_string(), + linker_flavor: LinkerFlavor::Em, + options: opts, + }) } diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index d91588db1834f..626fa374a1bd4 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -71,7 +71,8 @@ mod riscv_base; mod wasm32_base; mod vxworks_base; -#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, + RustcEncodable, RustcDecodable)] pub enum LinkerFlavor { Em, Gcc, @@ -81,7 +82,8 @@ pub enum LinkerFlavor { PtxLinker, } -#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, + RustcEncodable, RustcDecodable)] pub enum LldFlavor { Wasm, Ld64, @@ -460,6 +462,7 @@ supported_targets! { ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), ("wasm32-unknown-unknown", wasm32_unknown_unknown), ("wasm32-wasi", wasm32_wasi), + ("wasm32-experimental-emscripten", wasm32_experimental_emscripten), ("thumbv6m-none-eabi", thumbv6m_none_eabi), ("thumbv7m-none-eabi", thumbv7m_none_eabi), @@ -486,7 +489,6 @@ supported_targets! { ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf), ("aarch64-unknown-none", aarch64_unknown_none), - ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat), ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx), @@ -689,9 +691,6 @@ pub struct TargetOptions { /// defined in libgcc. If this option is enabled, the target must provide /// `eh_unwind_resume` lang item. pub custom_unwind_resume: bool, - /// Whether the runtime startup code requires the `main` function be passed - /// `argc` and `argv` values. - pub main_needs_argc_argv: bool, /// Flag indicating whether ELF TLS (e.g., #[thread_local]) is available for /// this target. @@ -850,7 +849,6 @@ impl Default for TargetOptions { link_env_remove: Vec::new(), archive_format: "gnu".to_string(), custom_unwind_resume: false, - main_needs_argc_argv: true, allow_asm: true, has_elf_tls: false, obj_is_bitcode: false, @@ -1161,7 +1159,6 @@ impl Target { key!(archive_format); key!(allow_asm, bool); key!(custom_unwind_resume, bool); - key!(main_needs_argc_argv, bool); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); key!(no_integrated_as, bool); @@ -1379,7 +1376,6 @@ impl ToJson for Target { target_option_val!(archive_format); target_option_val!(allow_asm); target_option_val!(custom_unwind_resume); - target_option_val!(main_needs_argc_argv); target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); target_option_val!(no_integrated_as); diff --git a/src/librustc_target/spec/wasm32_experimental_emscripten.rs b/src/librustc_target/spec/wasm32_experimental_emscripten.rs new file mode 100644 index 0000000000000..b802bee25ae7a --- /dev/null +++ b/src/librustc_target/spec/wasm32_experimental_emscripten.rs @@ -0,0 +1,44 @@ +use super::{LinkArgs, LinkerFlavor, Target, TargetOptions}; + +pub fn target() -> Result { + let mut post_link_args = LinkArgs::new(); + post_link_args.insert(LinkerFlavor::Em, + vec!["-s".to_string(), + "WASM=1".to_string(), + "-s".to_string(), + "ASSERTIONS=1".to_string(), + "-s".to_string(), + "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(), + "-g3".to_string()]); + + let opts = TargetOptions { + dynamic_linking: false, + executables: true, + // Today emcc emits two files - a .js file to bootstrap and + // possibly interpret the wasm, and a .wasm file + exe_suffix: ".js".to_string(), + linker_is_gnu: true, + link_env: vec![("EMCC_WASM_BACKEND".to_string(), "1".to_string())], + allow_asm: false, + obj_is_bitcode: true, + is_like_emscripten: true, + max_atomic_width: Some(32), + post_link_args, + limit_rdylib_exports: false, + target_family: Some("unix".to_string()), + .. Default::default() + }; + Ok(Target { + llvm_target: "wasm32-unknown-unknown".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + target_os: "emscripten".to_string(), + target_env: String::new(), + target_vendor: "unknown".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), + arch: "wasm32".to_string(), + linker_flavor: LinkerFlavor::Em, + options: opts, + }) +} diff --git a/src/librustc_target/spec/wasm32_unknown_emscripten.rs b/src/librustc_target/spec/wasm32_unknown_emscripten.rs index 6a2c8c495372f..e0df36884bf56 100644 --- a/src/librustc_target/spec/wasm32_unknown_emscripten.rs +++ b/src/librustc_target/spec/wasm32_unknown_emscripten.rs @@ -1,46 +1,45 @@ -use super::wasm32_base; -use super::{LinkArgs, LinkerFlavor, Target, TargetOptions, PanicStrategy}; +use super::{LinkArgs, LinkerFlavor, Target, TargetOptions}; pub fn target() -> Result { + // FIXME(nikic) BINARYEN_TRAP_MODE=clamp is needed to avoid trapping in our + // -Zsaturating-float-casts implementation. This can be dropped if/when + // we have native fpto[su]i.sat intrinsics, or the implementation otherwise + // stops relying on non-trapping fpto[su]i. let mut post_link_args = LinkArgs::new(); post_link_args.insert(LinkerFlavor::Em, vec!["-s".to_string(), - "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(), - "-s".to_string(), - "ASSERTIONS=1".to_string(), + "BINARYEN=1".to_string(), "-s".to_string(), - "DISABLE_EXCEPTION_CATCHING=1".to_string(), + "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(), "-s".to_string(), - "ABORTING_MALLOC=0".to_string(), - // FIXME(tlively): Enable this linker option once libc type errors - // are resolved. See https://github.com/rust-lang/libc/pull/1478. - // "-Wl,--fatal-warnings".to_string(), - ]); + "BINARYEN_TRAP_MODE='clamp'".to_string()]); let opts = TargetOptions { - // emcc emits two files - a .js file to instantiate the wasm and supply platform - // functionality, and a .wasm file. + dynamic_linking: false, + executables: true, + // Today emcc emits two files - a .js file to bootstrap and + // possibly interpret the wasm, and a .wasm file exe_suffix: ".js".to_string(), - linker: None, linker_is_gnu: true, + allow_asm: false, + obj_is_bitcode: true, is_like_emscripten: true, - // FIXME(tlively): Emscripten supports unwinding, but we would have to pass - // -enable-emscripten-cxx-exceptions to LLVM at codegen time and merge - // https://reviews.llvm.org/rG5c3cdef84b82464756bb571c13c31cf7773860c3to use it. - panic_strategy: PanicStrategy::Abort, + max_atomic_width: Some(32), post_link_args, + limit_rdylib_exports: false, target_family: Some("unix".to_string()), - .. wasm32_base::options() + codegen_backend: "emscripten".to_string(), + .. Default::default() }; Ok(Target { - llvm_target: "wasm32-unknown-emscripten".to_string(), + llvm_target: "asmjs-unknown-emscripten".to_string(), target_endian: "little".to_string(), target_pointer_width: "32".to_string(), target_c_int_width: "32".to_string(), target_os: "emscripten".to_string(), target_env: String::new(), target_vendor: "unknown".to_string(), - data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), + data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(), arch: "wasm32".to_string(), linker_flavor: LinkerFlavor::Em, options: opts, diff --git a/src/librustc_target/spec/wasm32_wasi.rs b/src/librustc_target/spec/wasm32_wasi.rs index d5ef230dcf7d2..86978c05b15d0 100644 --- a/src/librustc_target/spec/wasm32_wasi.rs +++ b/src/librustc_target/spec/wasm32_wasi.rs @@ -101,10 +101,6 @@ pub fn target() -> Result { // without a main function. options.crt_static_allows_dylibs = true; - // WASI's `sys::args::init` function ignores its arguments; instead, - // `args::args()` makes the WASI API calls itself. - options.main_needs_argc_argv = false; - Ok(Target { llvm_target: "wasm32-wasi".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs index 8d136a1b65c79..54d580ec05d71 100644 --- a/src/librustc_traits/chalk_context/mod.rs +++ b/src/librustc_traits/chalk_context/mod.rs @@ -33,7 +33,7 @@ use rustc::traits::{ InEnvironment, ChalkCanonicalGoal, }; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, TyCtxt, InferConst}; use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use rustc::ty::query::Providers; use rustc::ty::subst::{GenericArg, GenericArgKind}; @@ -286,7 +286,7 @@ impl context::ContextOps> for ChalkContext<'tcx> { _ => false, }, GenericArgKind::Const(ct) => match ct.val { - ConstValue::Bound(debruijn, bound_ct) => { + ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)) => { debug_assert_eq!(debruijn, ty::INNERMOST); cvar == bound_ct } diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs index 13bbe021ccf34..6790f14f69bbd 100644 --- a/src/librustc_traits/chalk_context/program_clauses/builtin.rs +++ b/src/librustc_traits/chalk_context/program_clauses/builtin.rs @@ -266,10 +266,7 @@ crate fn assemble_builtin_copy_clone_impls<'tcx>( let closure_ty = generic_types::closure(tcx, def_id); let upvar_tys: Vec<_> = match &closure_ty.kind { ty::Closure(_, substs) => { - substs.as_closure() - .upvar_tys(def_id, tcx) - .map(|ty| GenericArg::from(ty)) - .collect() + substs.upvar_tys(def_id, tcx).map(|ty| GenericArg::from(ty)).collect() }, _ => bug!(), }; diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs index 49d76681196af..8facec1e9e35f 100644 --- a/src/librustc_traits/chalk_context/resolvent_ops.rs +++ b/src/librustc_traits/chalk_context/resolvent_ops.rs @@ -16,7 +16,7 @@ use rustc::traits::{ Environment, InEnvironment, }; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, InferConst}; use rustc::ty::subst::GenericArg; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc::mir::interpret::ConstValue; @@ -287,7 +287,10 @@ impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> { a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - if let ty::Const { val: ConstValue::Bound(debruijn, bound_ct), .. } = a { + if let ty::Const { + val: ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)), + .. + } = a { if *debruijn == self.binder_index { self.unify_free_answer_var(*bound_ct, b.into())?; return Ok(b); @@ -296,8 +299,14 @@ impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> { match (a, b) { ( - ty::Const { val: ConstValue::Bound(a_debruijn, a_bound), .. }, - ty::Const { val: ConstValue::Bound(b_debruijn, b_bound), .. }, + ty::Const { + val: ConstValue::Infer(InferConst::Canonical(a_debruijn, a_bound)), + .. + }, + ty::Const { + val: ConstValue::Infer(InferConst::Canonical(b_debruijn, b_bound)), + .. + }, ) => { assert_eq!(a_debruijn, b_debruijn); assert_eq!(a_bound, b_bound); diff --git a/src/librustc_traits/chalk_context/unify.rs b/src/librustc_traits/chalk_context/unify.rs index 5959c2ea5ca14..1f9090324414b 100644 --- a/src/librustc_traits/chalk_context/unify.rs +++ b/src/librustc_traits/chalk_context/unify.rs @@ -65,7 +65,7 @@ impl TypeRelatingDelegate<'tcx> for &mut ChalkTypeRelatingDelegate<'_, 'tcx> { self.infcx.create_next_universe() } - fn next_existential_region_var(&mut self, _was_placeholder: bool) -> ty::Region<'tcx> { + fn next_existential_region_var(&mut self) -> ty::Region<'tcx> { self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP)) } diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index c1316f415a559..a36b381bed343 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -80,30 +80,22 @@ fn dropck_outlives<'tcx>( let mut fulfill_cx = TraitEngine::new(infcx.tcx); let cause = ObligationCause::dummy(); - let mut constraints = DtorckConstraint::empty(); while let Some((ty, depth)) = ty_stack.pop() { - info!("{} kinds, {} overflows, {} ty_stack", - result.kinds.len(), result.overflows.len(), ty_stack.len()); - dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?; + let DtorckConstraint { + dtorck_types, + outlives, + overflows, + } = dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty)?; // "outlives" represent types/regions that may be touched // by a destructor. - result.kinds.extend(constraints.outlives.drain(..)); - result.overflows.extend(constraints.overflows.drain(..)); - - // If we have even one overflow, we should stop trying to evaluate further -- - // chances are, the subsequent overflows for this evaluation won't provide useful - // information and will just decrease the speed at which we can emit these errors - // (since we'll be printing for just that much longer for the often enormous types - // that result here). - if result.overflows.len() >= 1 { - break; - } + result.kinds.extend(outlives); + result.overflows.extend(overflows); // dtorck types are "types that will get dropped but which // do not themselves define a destructor", more or less. We have // to push them onto the stack to be expanded. - for ty in constraints.dtorck_types.drain(..) { + for ty in dtorck_types { match infcx.at(&cause, param_env).normalize(&ty) { Ok(Normalized { value: ty, @@ -160,23 +152,21 @@ fn dtorck_constraint_for_ty<'tcx>( for_ty: Ty<'tcx>, depth: usize, ty: Ty<'tcx>, - constraints: &mut DtorckConstraint<'tcx>, -) -> Result<(), NoSolution> { +) -> Result, NoSolution> { debug!( "dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty ); if depth >= *tcx.sess.recursion_limit.get() { - constraints.overflows.push(ty); - return Ok(()); - } - - if tcx.trivial_dropck_outlives(ty) { - return Ok(()); + return Ok(DtorckConstraint { + outlives: vec![], + dtorck_types: vec![], + overflows: vec![ty], + }); } - match ty.kind { + let result = match ty.kind { ty::Bool | ty::Char | ty::Int(_) @@ -191,20 +181,22 @@ fn dtorck_constraint_for_ty<'tcx>( | ty::FnPtr(_) | ty::GeneratorWitness(..) => { // these types never have a destructor + Ok(DtorckConstraint::empty()) } ty::Array(ety, _) | ty::Slice(ety) => { // single-element containers, behave like their element - dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety, constraints)?; + dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety) } - ty::Tuple(tys) => for ty in tys.iter() { - dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty.expect_ty(), constraints)?; - }, + ty::Tuple(tys) => tys.iter() + .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty.expect_ty())) + .collect(), - ty::Closure(def_id, substs) => for ty in substs.as_closure().upvar_tys(def_id, tcx) { - dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?; - } + ty::Closure(def_id, substs) => substs + .upvar_tys(def_id, tcx) + .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty)) + .collect(), ty::Generator(def_id, substs, _movability) => { // rust-lang/rust#49918: types can be constructed, stored @@ -230,8 +222,17 @@ fn dtorck_constraint_for_ty<'tcx>( // derived from lifetimes attached to the upvars, and we // *do* incorporate the upvars here. - constraints.outlives.extend(substs.as_generator().upvar_tys(def_id, tcx) - .map(|t| -> ty::subst::GenericArg<'tcx> { t.into() })); + let constraint = DtorckConstraint { + outlives: substs.upvar_tys(def_id, tcx).map(|t| t.into()).collect(), + dtorck_types: vec![], + overflows: vec![], + }; + debug!( + "dtorck_constraint: generator {:?} => {:?}", + def_id, constraint + ); + + Ok(constraint) } ty::Adt(def, substs) => { @@ -240,34 +241,41 @@ fn dtorck_constraint_for_ty<'tcx>( outlives, overflows, } = tcx.at(span).adt_dtorck_constraint(def.did)?; - // FIXME: we can try to recursively `dtorck_constraint_on_ty` - // there, but that needs some way to handle cycles. - constraints.dtorck_types.extend(dtorck_types.subst(tcx, substs)); - constraints.outlives.extend(outlives.subst(tcx, substs)); - constraints.overflows.extend(overflows.subst(tcx, substs)); + Ok(DtorckConstraint { + // FIXME: we can try to recursively `dtorck_constraint_on_ty` + // there, but that needs some way to handle cycles. + dtorck_types: dtorck_types.subst(tcx, substs), + outlives: outlives.subst(tcx, substs), + overflows: overflows.subst(tcx, substs), + }) } // Objects must be alive in order for their destructor // to be called. - ty::Dynamic(..) => { - constraints.outlives.push(ty.into()); - }, + ty::Dynamic(..) => Ok(DtorckConstraint { + outlives: vec![ty.into()], + dtorck_types: vec![], + overflows: vec![], + }), // Types that can't be resolved. Pass them forward. - ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => { - constraints.dtorck_types.push(ty); - }, + ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => Ok(DtorckConstraint { + outlives: vec![], + dtorck_types: vec![ty], + overflows: vec![], + }), ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => { // By the time this code runs, all type variables ought to // be fully resolved. - return Err(NoSolution) + Err(NoSolution) } - } + }; - Ok(()) + debug!("dtorck_constraint_for_ty({:?}) = {:?}", ty, result); + result } /// Calculates the dtorck constraint for a type. @@ -293,11 +301,10 @@ crate fn adt_dtorck_constraint( return Ok(result); } - let mut result = DtorckConstraint::empty(); - for field in def.all_fields() { - let fty = tcx.type_of(field.did); - dtorck_constraint_for_ty(tcx, span, fty, 0, fty, &mut result)?; - } + let mut result = def.all_fields() + .map(|field| tcx.type_of(field.did)) + .map(|fty| dtorck_constraint_for_ty(tcx, span, fty, 0, fty)) + .collect::, NoSolution>>()?; result.outlives.extend(tcx.destructor_constraints(def)); dedup_dtorck_constraint(&mut result); diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs index dc7eeead30cbe..30a1814d0f83e 100644 --- a/src/librustc_traits/evaluate_obligation.rs +++ b/src/librustc_traits/evaluate_obligation.rs @@ -17,12 +17,10 @@ fn evaluate_obligation<'tcx>( tcx: TyCtxt<'tcx>, canonical_goal: CanonicalPredicateGoal<'tcx>, ) -> Result { - debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal); tcx.infer_ctxt().enter_with_canonical( DUMMY_SP, &canonical_goal, |ref infcx, goal, _canonical_inference_vars| { - debug!("evaluate_obligation: goal={:#?}", goal); let ParamEnvAnd { param_env, value: predicate, diff --git a/src/librustc_traits/generic_types.rs b/src/librustc_traits/generic_types.rs index cc5348623fabd..e4d15a35137cc 100644 --- a/src/librustc_traits/generic_types.rs +++ b/src/librustc_traits/generic_types.rs @@ -69,13 +69,13 @@ crate fn fn_def(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { } crate fn closure(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { - tcx.mk_closure(def_id, InternalSubsts::bound_vars_for_item(tcx, def_id)) + tcx.mk_closure(def_id, ty::ClosureSubsts { + substs: InternalSubsts::bound_vars_for_item(tcx, def_id), + }) } crate fn generator(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { - tcx.mk_generator( - def_id, - InternalSubsts::bound_vars_for_item(tcx, def_id), - hir::GeneratorMovability::Movable - ) + tcx.mk_generator(def_id, ty::GeneratorSubsts { + substs: InternalSubsts::bound_vars_for_item(tcx, def_id), + }, hir::GeneratorMovability::Movable) } diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 0df367fcca83c..4c30227150fb1 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -218,7 +218,7 @@ fn program_clauses_for_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> { let implemented_from_env = Clause::ForAll(ty::Binder::bind(implemented_from_env)); - let predicates = tcx.predicates_defined_on(def_id).predicates; + let predicates = &tcx.predicates_defined_on(def_id).predicates; // Warning: these where clauses are not substituted for bound vars yet, // so that we don't need to adjust binders in the `FromEnv` rules below @@ -319,7 +319,7 @@ fn program_clauses_for_impl(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> { let trait_pred = ty::TraitPredicate { trait_ref }.lower(); // `WC` - let predicates = tcx.predicates_of(def_id).predicates; + let predicates = &tcx.predicates_of(def_id).predicates; let where_clauses = predicates .iter() .map(|(wc, _)| wc.lower()) diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index a6644258be280..ac3966676838a 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -20,4 +20,3 @@ rustc_target = { path = "../librustc_target" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -rustc_index = { path = "../librustc_index" } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index aa05a08686a99..5ab2ca280d5cd 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -54,7 +54,8 @@ pub trait AstConv<'tcx> { /// but this can lead to cycle errors. The problem is that we have /// to do this resolution *in order to create the predicates in /// the first place*. Hence, we have this "special pass". - fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx>; + fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) + -> &'tcx ty::GenericPredicates<'tcx>; /// Returns the lifetime to use when a lifetime is omitted (and not elided). fn re_infer( @@ -131,7 +132,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { let tcx = self.tcx(); let lifetime_name = |def_id| { - tcx.hir().name(tcx.hir().as_local_hir_id(def_id).unwrap()) + tcx.hir().name(tcx.hir().as_local_hir_id(def_id).unwrap()).as_interned_str() }; let r = match tcx.named_region(lifetime.hir_id) { @@ -215,6 +216,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Report error if there is an explicit type parameter when using `impl Trait`. fn check_impl_trait( tcx: TyCtxt<'_>, + span: Span, seg: &hir::PathSegment, generics: &ty::Generics, ) -> bool { @@ -227,28 +229,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }); if explicit && impl_trait { - let spans = - seg.generic_args().args - .iter() - .filter_map(|arg| - match arg { - GenericArg::Type(_) => Some(arg.span()), - _ => None - }) - .collect::>(); - let mut err = struct_span_err! { tcx.sess, - spans.clone(), + span, E0632, - "cannot provide explicit generic arguments when `impl Trait` is \ - used in argument position" + "cannot provide explicit type parameters when `impl Trait` is \ + used in argument position." }; - for span in spans { - err.span_label(span, "explicit generic argument not allowed"); - } - err.emit(); } @@ -267,7 +255,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let empty_args = P(hir::GenericArgs { args: HirVec::new(), bindings: HirVec::new(), parenthesized: false, }); - let suppress_mismatch = Self::check_impl_trait(tcx, seg, &def); + let suppress_mismatch = Self::check_impl_trait(tcx, span, seg, &def); Self::check_generic_arg_count( tcx, span, @@ -964,8 +952,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.sess.span_warn( span, "default bound relaxed for a type parameter, but \ - this does nothing because the given bound is not \ - a default; only `?Sized` is supported", + this does nothing because the given bound is not \ + a default. Only `?Sized` is supported", ); } } @@ -1287,7 +1275,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span, item.trait_ref().def_id(), object_safety_violations - ).emit(); + ) + .map(|mut err| err.emit()); return tcx.types.err; } } @@ -2035,7 +2024,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let item_def_id = tcx.hir().local_def_id(item_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; - tcx.mk_ty_param(index, tcx.hir().name(hir_id)) + tcx.mk_ty_param(index, tcx.hir().name(hir_id).as_interned_str()) } Res::SelfTy(Some(_), None) => { // `Self` in trait or type alias. @@ -2159,6 +2148,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // handled specially and will not descend into this routine. self.ty_infer(None, ast_ty.span) } + hir::TyKind::CVarArgs(lt) => { + let va_list_did = match tcx.lang_items().va_list() { + Some(did) => did, + None => span_bug!(ast_ty.span, + "`va_list` lang item required for variadics"), + }; + let region = self.ast_region_to_region(<, None); + tcx.type_of(va_list_did).subst(tcx, &[region.into()]) + } hir::TyKind::Err => { tcx.types.err } @@ -2216,7 +2214,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let item_def_id = tcx.hir().local_def_id(item_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)]; - let name = tcx.hir().name(hir_id); + let name = tcx.hir().name(hir_id).as_interned_str(); const_.val = ConstValue::Param(ty::ParamConst::new(index, name)); } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index a1daed005f302..13b6b1b8aa08d 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`. // // FIXME(60707): Consider removing hack with principled solution. - self.check_expr_has_type_or_error(discrim, self.tcx.types.bool, |_| {}) + self.check_expr_has_type_or_error(discrim, self.tcx.types.bool) } else { self.demand_discriminant_type(arms, discrim) }; @@ -106,9 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(g) = &arm.guard { self.diverges.set(pats_diverge); match g { - hir::Guard::If(e) => { - self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {}) - } + hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool), }; } @@ -444,7 +442,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: TypeVariableOriginKind::TypeInference, span: discrim.span, }); - self.check_expr_has_type_or_error(discrim, discrim_ty, |_| {}); + self.check_expr_has_type_or_error(discrim, discrim_ty); discrim_ty } } diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 300b730b5bbfa..7e0a3e781883e 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -7,7 +7,6 @@ use hir::def::Res; use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::subst::SubstsRef; use rustc::{infer, traits}; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_target::spec::abi; @@ -398,17 +397,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .0; let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig); + let inputs = if fn_sig.c_variadic { + if fn_sig.inputs().len() > 1 { + &fn_sig.inputs()[..fn_sig.inputs().len() - 1] + } else { + span_bug!(call_expr.span, + "C-variadic functions are only valid with one or more fixed arguments"); + } + } else { + &fn_sig.inputs()[..] + }; // Call the generic checker. let expected_arg_tys = self.expected_inputs_for_expected_output( call_expr.span, expected, fn_sig.output(), - fn_sig.inputs(), + inputs, ); self.check_argument_types( call_expr.span, call_expr, - fn_sig.inputs(), + inputs, &expected_arg_tys[..], arg_exprs, fn_sig.c_variadic, @@ -481,7 +490,7 @@ pub struct DeferredCallResolution<'tcx> { adjustments: Vec>, fn_sig: ty::FnSig<'tcx>, closure_def_id: DefId, - closure_substs: SubstsRef<'tcx>, + closure_substs: ty::ClosureSubsts<'tcx>, } impl<'a, 'tcx> DeferredCallResolution<'tcx> { diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 9cbde276ae97c..dfeb5fb958cd8 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -428,36 +428,21 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.report_cast_to_unsized_type(fcx); } else if self.expr_ty.references_error() || self.cast_ty.references_error() { // No sense in giving duplicate error messages + } else if self.try_coercion_cast(fcx) { + self.trivial_cast_lint(fcx); + debug!(" -> CoercionCast"); + fcx.tables.borrow_mut().set_coercion_cast(self.expr.hir_id.local_id); + } else { - match self.try_coercion_cast(fcx) { - Ok(()) => { - self.trivial_cast_lint(fcx); - debug!(" -> CoercionCast"); - fcx.tables.borrow_mut() - .set_coercion_cast(self.expr.hir_id.local_id); - } - Err(ty::error::TypeError::ObjectUnsafeCoercion(did)) => { - self.report_object_unsafe_cast(&fcx, did); - } - Err(_) => { - match self.do_check(fcx) { - Ok(k) => { - debug!(" -> {:?}", k); - } - Err(e) => self.report_cast_error(fcx, e), - }; + match self.do_check(fcx) { + Ok(k) => { + debug!(" -> {:?}", k); } + Err(e) => self.report_cast_error(fcx, e), }; } } - fn report_object_unsafe_cast(&self, fcx: &FnCtxt<'a, 'tcx>, did: DefId) { - let violations = fcx.tcx.object_safety_violations(did); - let mut err = fcx.tcx.report_object_safety_error(self.cast_span, did, violations); - err.note(&format!("required by cast to type '{}'", fcx.ty_to_string(self.cast_ty))); - err.emit(); - } - /// Checks a cast, and report an error if one exists. In some cases, this /// can return Ok and create type errors in the fcx rather than returning /// directly. coercion-cast is handled in check instead of here. @@ -661,14 +646,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { } } - fn try_coercion_cast( - &self, - fcx: &FnCtxt<'a, 'tcx>, - ) -> Result<(), ty::error::TypeError<'_>> { - match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No) { - Ok(_) => Ok(()), - Err(err) => Err(err), - } + fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> bool { + fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No).is_ok() } } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 4f4133954cf1d..bdf8f3b1d4ae6 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -113,25 +113,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }); if let Some(GeneratorTypes { yield_ty, interior, movability }) = generator_types { - let generator_substs = substs.as_generator(); + let substs = ty::GeneratorSubsts { substs }; self.demand_eqtype( expr.span, yield_ty, - generator_substs.yield_ty(expr_def_id, self.tcx), + substs.yield_ty(expr_def_id, self.tcx), ); self.demand_eqtype( expr.span, liberated_sig.output(), - generator_substs.return_ty(expr_def_id, self.tcx), + substs.return_ty(expr_def_id, self.tcx), ); self.demand_eqtype( expr.span, interior, - generator_substs.witness(expr_def_id, self.tcx), + substs.witness(expr_def_id, self.tcx), ); return self.tcx.mk_generator(expr_def_id, substs, movability); } + let substs = ty::ClosureSubsts { substs }; let closure_type = self.tcx.mk_closure(expr_def_id, substs); debug!( @@ -160,14 +161,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_eqtype( expr.span, sig_fn_ptr_ty, - substs.as_closure().sig_ty(expr_def_id, self.tcx), + substs.closure_sig_ty(expr_def_id, self.tcx), ); if let Some(kind) = opt_kind { self.demand_eqtype( expr.span, kind.to_ty(self.tcx), - substs.as_closure().kind_ty(expr_def_id, self.tcx), + substs.closure_kind_ty(expr_def_id, self.tcx), ); } @@ -336,7 +337,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> ClosureSignatures<'tcx> { debug!("sig_of_closure_no_expectation()"); - let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); + let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl); self.closure_sigs(expr_def_id, body, bound_sig) } @@ -489,7 +490,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // (See comment on `sig_of_closure_with_expectation` for the // meaning of these letters.) - let supplied_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); + let supplied_sig = self.supplied_sig_of_closure(expr_def_id, decl); debug!( "check_supplied_sig_against_expectation: supplied_sig={:?}", @@ -590,41 +591,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, expr_def_id: DefId, decl: &hir::FnDecl, - body: &hir::Body, ) -> ty::PolyFnSig<'tcx> { let astconv: &dyn AstConv<'_> = self; - debug!( - "supplied_sig_of_closure(decl={:?}, body.generator_kind={:?})", - decl, - body.generator_kind, - ); - // First, convert the types that the user supplied (if any). let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a)); let supplied_return = match decl.output { hir::Return(ref output) => astconv.ast_ty_to_ty(&output), - hir::DefaultReturn(_) => match body.generator_kind { - // In the case of the async block that we create for a function body, - // we expect the return type of the block to match that of the enclosing - // function. - Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn)) => { - debug!("supplied_sig_of_closure: closure is async fn body"); - self.deduce_future_output_from_obligations(expr_def_id) - .unwrap_or_else(|| { - // AFAIK, deducing the future output - // always succeeds *except* in error cases - // like #65159. I'd like to return Error - // here, but I can't because I can't - // easily (and locally) prove that we - // *have* reported an - // error. --nikomatsakis - astconv.ty_infer(None, decl.output.span()) - }) - } - - _ => astconv.ty_infer(None, decl.output.span()), - } + hir::DefaultReturn(_) => astconv.ty_infer(None, decl.output.span()), }; let result = ty::Binder::bind(self.tcx.mk_fn_sig( @@ -646,116 +620,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { result } - /// Invoked when we are translating the generator that results - /// from desugaring an `async fn`. Returns the "sugared" return - /// type of the `async fn` -- that is, the return type that the - /// user specified. The "desugared" return type is a `impl - /// Future`, so we do this by searching through the - /// obligations to extract the `T`. - fn deduce_future_output_from_obligations( - &self, - expr_def_id: DefId, - ) -> Option> { - debug!("deduce_future_output_from_obligations(expr_def_id={:?})", expr_def_id); - - let ret_coercion = - self.ret_coercion - .as_ref() - .unwrap_or_else(|| span_bug!( - self.tcx.def_span(expr_def_id), - "async fn generator outside of a fn" - )); - - // In practice, the return type of the surrounding function is - // always a (not yet resolved) inference variable, because it - // is the hidden type for an `impl Trait` that we are going to - // be inferring. - let ret_ty = ret_coercion.borrow().expected_ty(); - let ret_ty = self.inh.infcx.shallow_resolve(ret_ty); - let ret_vid = match ret_ty.kind { - ty::Infer(ty::TyVar(ret_vid)) => ret_vid, - _ => { - span_bug!( - self.tcx.def_span(expr_def_id), - "async fn generator return type not an inference variable" - ) - } - }; - - // Search for a pending obligation like - // - // `::Output = T` - // - // where R is the return type we are expecting. This type `T` - // will be our output. - let output_ty = self.obligations_for_self_ty(ret_vid) - .find_map(|(_, obligation)| { - if let ty::Predicate::Projection(ref proj_predicate) = obligation.predicate { - self.deduce_future_output_from_projection( - obligation.cause.span, - proj_predicate - ) - } else { - None - } - }); - - debug!("deduce_future_output_from_obligations: output_ty={:?}", output_ty); - output_ty - } - - /// Given a projection like - /// - /// `::Output = T` - /// - /// where `X` is some type that has no late-bound regions, returns - /// `Some(T)`. If the projection is for some other trait, returns - /// `None`. - fn deduce_future_output_from_projection( - &self, - cause_span: Span, - predicate: &ty::PolyProjectionPredicate<'tcx>, - ) -> Option> { - debug!("deduce_future_output_from_projection(predicate={:?})", predicate); - - // We do not expect any bound regions in our predicate, so - // skip past the bound vars. - let predicate = match predicate.no_bound_vars() { - Some(p) => p, - None => { - debug!("deduce_future_output_from_projection: has late-bound regions"); - return None; - } - }; - - // Check that this is a projection from the `Future` trait. - let trait_ref = predicate.projection_ty.trait_ref(self.tcx); - let future_trait = self.tcx.lang_items().future_trait().unwrap(); - if trait_ref.def_id != future_trait { - debug!("deduce_future_output_from_projection: not a future"); - return None; - } - - // The `Future` trait has only one associted item, `Output`, - // so check that this is what we see. - let output_assoc_item = self.tcx.associated_items(future_trait).nth(0).unwrap().def_id; - if output_assoc_item != predicate.projection_ty.item_def_id { - span_bug!( - cause_span, - "projecting associated item `{:?}` from future, which is not Output `{:?}`", - predicate.projection_ty.item_def_id, - output_assoc_item, - ); - } - - // Extract the type from the projection. Note that there can - // be no bound variables in this type because the "self type" - // does not have any regions in it. - let output_ty = self.resolve_vars_if_possible(&predicate.ty); - debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty); - Some(output_ty) - } - /// Converts the types that the user supplied, in case that doing /// so should yield an error, but returns back a signature where /// all parameters are of type `TyErr`. diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index f79351dc90310..564a0eac75539 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -61,11 +61,10 @@ use rustc::traits::{self, ObligationCause, ObligationCauseCode}; use rustc::ty::adjustment::{ Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast }; -use rustc::ty::{self, TypeAndMut, Ty}; +use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts}; use rustc::ty::fold::TypeFoldable; use rustc::ty::error::TypeError; use rustc::ty::relate::RelateResult; -use rustc::ty::subst::SubstsRef; use smallvec::{smallvec, SmallVec}; use std::ops::Deref; use syntax::feature_gate; @@ -197,16 +196,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // a "spurious" type variable, and we don't want to have that // type variable in memory if the coercion fails. let unsize = self.commit_if_ok(|_| self.coerce_unsized(a, b)); - match unsize { - Ok(_) => { - debug!("coerce: unsize successful"); - return unsize; - } - Err(TypeError::ObjectUnsafeCoercion(did)) => { - debug!("coerce: unsize not object safe"); - return Err(TypeError::ObjectUnsafeCoercion(did)); - } - Err(_) => {} + if unsize.is_ok() { + debug!("coerce: unsize successful"); + return unsize; } debug!("coerce: unsize failed"); @@ -547,11 +539,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let mut selcx = traits::SelectionContext::new(self); // Create an obligation for `Source: CoerceUnsized`. - let cause = ObligationCause::new( - self.cause.span, - self.body_id, - ObligationCauseCode::Coercion { source, target }, - ); + let cause = ObligationCause::misc(self.cause.span, self.body_id); // Use a FIFO queue for this custom fulfillment procedure. // @@ -578,15 +566,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let obligation = queue.remove(0); debug!("coerce_unsized resolve step: {:?}", obligation); let trait_ref = match obligation.predicate { - ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => { - if unsize_did == tr.def_id() { - let sty = &tr.skip_binder().input_types().nth(1).unwrap().kind; - if let ty::Tuple(..) = sty { + ty::Predicate::Trait(ref t) if traits.contains(&t.def_id()) => { + if unsize_did == t.def_id() { + if let ty::Tuple(..) = &t.skip_binder().input_types().nth(1).unwrap().kind { debug!("coerce_unsized: found unsized tuple coercion"); has_unsized_tuple_coercion = true; } } - tr.clone() + t.clone() } _ => { coercion.obligations.push(obligation); @@ -740,7 +727,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { fn coerce_closure_to_fn(&self, a: Ty<'tcx>, def_id_a: DefId, - substs_a: SubstsRef<'tcx>, + substs_a: ClosureSubsts<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { //! Attempts to coerce from the type of a non-capturing closure @@ -824,7 +811,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { target: Ty<'tcx>, allow_two_phase: AllowTwoPhase, ) -> RelateResult<'tcx, Ty<'tcx>> { - let source = self.resolve_vars_with_obligations(expr_ty); + let source = self.resolve_type_vars_with_obligations(expr_ty); debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target); let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable); @@ -842,7 +829,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Same as `try_coerce()`, but without side-effects. pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool { - let source = self.resolve_vars_with_obligations(expr_ty); + let source = self.resolve_type_vars_with_obligations(expr_ty); debug!("coercion::can({:?} -> {:?})", source, target); let cause = self.cause(syntax_pos::DUMMY_SP, ObligationCauseCode::ExprAssignable); @@ -866,8 +853,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { -> RelateResult<'tcx, Ty<'tcx>> where E: AsCoercionSite { - let prev_ty = self.resolve_vars_with_obligations(prev_ty); - let new_ty = self.resolve_vars_with_obligations(new_ty); + let prev_ty = self.resolve_type_vars_with_obligations(prev_ty); + let new_ty = self.resolve_type_vars_with_obligations(new_ty); debug!("coercion::try_find_coercion_lub({:?}, {:?})", prev_ty, new_ty); // Special-case that coercion alone cannot handle: @@ -1176,20 +1163,18 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { fcx.try_coerce(expression, expression_ty, self.expected_ty, AllowTwoPhase::No) } else { match self.expressions { - Expressions::Dynamic(ref exprs) => fcx.try_find_coercion_lub( - cause, - exprs, - self.merged_ty(), - expression, - expression_ty, - ), - Expressions::UpFront(ref coercion_sites) => fcx.try_find_coercion_lub( - cause, - &coercion_sites[0..self.pushed], - self.merged_ty(), - expression, - expression_ty, - ), + Expressions::Dynamic(ref exprs) => + fcx.try_find_coercion_lub(cause, + exprs, + self.merged_ty(), + expression, + expression_ty), + Expressions::UpFront(ref coercion_sites) => + fcx.try_find_coercion_lub(cause, + &coercion_sites[0..self.pushed], + self.merged_ty(), + expression, + expression_ty), } } } else { @@ -1231,7 +1216,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { self.pushed += 1; } } - Err(coercion_error) => { + Err(err) => { let (expected, found) = if label_expression_as_expected { // In the case where this is a "forced unit", like // `break`, we want to call the `()` "expected" @@ -1247,42 +1232,41 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { (self.final_ty.unwrap_or(self.expected_ty), expression_ty) }; - let mut err; + let mut db; match cause.code { ObligationCauseCode::ReturnNoExpression => { - err = struct_span_err!( + db = struct_span_err!( fcx.tcx.sess, cause.span, E0069, "`return;` in a function whose return type is not `()`"); - err.span_label(cause.span, "return type is not `()`"); + db.span_label(cause.span, "return type is not `()`"); } ObligationCauseCode::BlockTailExpression(blk_id) => { let parent_id = fcx.tcx.hir().get_parent_node(blk_id); - err = self.report_return_mismatched_types( + db = self.report_return_mismatched_types( cause, expected, found, - coercion_error, + err, fcx, parent_id, expression.map(|expr| (expr, blk_id)), ); } ObligationCauseCode::ReturnValue(id) => { - err = self.report_return_mismatched_types( - cause, expected, found, coercion_error, fcx, id, None); + db = self.report_return_mismatched_types( + cause, expected, found, err, fcx, id, None); } _ => { - err = fcx.report_mismatched_types(cause, expected, found, coercion_error); + db = fcx.report_mismatched_types(cause, expected, found, err); } } if let Some(augment_error) = augment_error { - augment_error(&mut err); + augment_error(&mut db); } // Error possibly reported in `check_assign` so avoid emitting error again. - err.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected)) - .is_some()); + db.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected)).is_some()); self.final_ty = Some(fcx.tcx.types.err); } @@ -1294,12 +1278,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, - ty_err: TypeError<'tcx>, + err: TypeError<'tcx>, fcx: &FnCtxt<'a, 'tcx>, id: hir::HirId, expression: Option<(&'tcx hir::Expr, hir::HirId)>, ) -> DiagnosticBuilder<'a> { - let mut err = fcx.report_mismatched_types(cause, expected, found, ty_err); + let mut db = fcx.report_mismatched_types(cause, expected, found, err); let mut pointing_at_return_type = false; let mut return_sp = None; @@ -1310,7 +1294,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { let parent_id = fcx.tcx.hir().get_parent_node(id); let fn_decl = if let Some((expr, blk_id)) = expression { pointing_at_return_type = fcx.suggest_mismatched_types_on_tail( - &mut err, + &mut db, expr, expected, found, @@ -1318,16 +1302,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { blk_id, ); let parent = fcx.tcx.hir().get(parent_id); - if let (Some(match_expr), true, false) = ( - fcx.tcx.hir().get_match_if_cause(expr.hir_id), - expected.is_unit(), - pointing_at_return_type, - ) { - if match_expr.span.desugaring_kind().is_none() { - err.span_label(match_expr.span, "expected this to be `()`"); - fcx.suggest_semicolon_at_end(match_expr.span, &mut err); - } - } fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main)) } else { fcx.get_fn_decl(parent_id) @@ -1336,20 +1310,20 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { if let (Some((fn_decl, can_suggest)), _) = (fn_decl, pointing_at_return_type) { if expression.is_none() { pointing_at_return_type |= fcx.suggest_missing_return_type( - &mut err, &fn_decl, expected, found, can_suggest); + &mut db, &fn_decl, expected, found, can_suggest); } if !pointing_at_return_type { return_sp = Some(fn_decl.output.span()); // `impl Trait` return type } } if let (Some(sp), Some(return_sp)) = (fcx.ret_coercion_span.borrow().as_ref(), return_sp) { - err.span_label(return_sp, "expected because this return type..."); - err.span_label( *sp, format!( + db.span_label(return_sp, "expected because this return type..."); + db.span_label( *sp, format!( "...is found to be `{}` here", - fcx.resolve_vars_with_obligations(expected), + fcx.resolve_type_vars_with_obligations(expected), )); } - err + db } pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> { diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 3509d6566ec93..2ea0afb179356 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -108,16 +108,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, allow_two_phase: AllowTwoPhase) -> (Ty<'tcx>, Option>) { - let expected = self.resolve_vars_with_obligations(expected); + let expected = self.resolve_type_vars_with_obligations(expected); let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase) { Ok(ty) => return (ty, None), Err(e) => e }; - let expr = expr.peel_drop_temps(); let cause = self.misc(expr.span); - let expr_ty = self.resolve_vars_with_obligations(checked_ty); + let expr_ty = self.resolve_type_vars_with_obligations(checked_ty); let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e); if self.is_assign_to_bool(expr, expected) { @@ -350,10 +349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the span is from a macro, then it's hard to extract the text // and make a good suggestion, so don't bother. - let is_macro = sp.from_expansion() && sp.desugaring_kind().is_none(); - - // `ExprKind::DropTemps` is semantically irrelevant for these suggestions. - let expr = expr.peel_drop_temps(); + let is_macro = sp.from_expansion(); match (&expr.kind, &expected.kind, &checked_ty.kind) { (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) { diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 0c8df9bad448f..cb03af46f3dbb 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -3,10 +3,10 @@ use crate::check::regionck::RegionCtxt; use crate::hir; use crate::hir::def_id::DefId; use rustc::infer::outlives::env::OutlivesEnvironment; -use rustc::infer::{InferOk, SuppressRegionErrors}; +use rustc::infer::{self, InferOk, SuppressRegionErrors}; use rustc::middle::region; use rustc::traits::{ObligationCause, TraitEngine, TraitEngineExt}; -use rustc::ty::subst::{Subst, SubstsRef}; +use rustc::ty::subst::{Subst, SubstsRef, GenericArgKind}; use rustc::ty::{self, Ty, TyCtxt}; use crate::util::common::ErrorReported; @@ -44,7 +44,7 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro ensure_drop_predicates_are_implied_by_item_defn( tcx, drop_impl_did, - dtor_predicates, + &dtor_predicates, adt_def.did, self_to_impl_substs, ) @@ -140,7 +140,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( tcx: TyCtxt<'tcx>, drop_impl_did: DefId, - dtor_predicates: ty::GenericPredicates<'tcx>, + dtor_predicates: &ty::GenericPredicates<'tcx>, self_type_did: DefId, self_to_impl_substs: SubstsRef<'tcx>, ) -> Result<(), ErrorReported> { @@ -199,7 +199,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( // just to look for all the predicates directly. assert_eq!(dtor_predicates.parent, None); - for (predicate, _) in dtor_predicates.predicates { + for (predicate, _) in &dtor_predicates.predicates { // (We do not need to worry about deep analysis of type // expressions etc because the Drop impls are already forced // to take on a structure that is roughly an alpha-renaming of @@ -233,21 +233,87 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( result } -/// This function is not only checking that the dropck obligations are met for -/// the given type, but it's also currently preventing non-regular recursion in -/// types from causing stack overflows (dropck_no_diverge_on_nonregular_*.rs). -crate fn check_drop_obligations<'a, 'tcx>( +/// This function confirms that the type +/// expression `typ` conforms to the "Drop Check Rule" from the Sound +/// Generic Drop RFC (#769). +/// +/// ---- +/// +/// The simplified (*) Drop Check Rule is the following: +/// +/// Let `v` be some value (either temporary or named) and 'a be some +/// lifetime (scope). If the type of `v` owns data of type `D`, where +/// +/// * (1.) `D` has a lifetime- or type-parametric Drop implementation, +/// (where that `Drop` implementation does not opt-out of +/// this check via the `may_dangle` +/// attribute), and +/// * (2.) the structure of `D` can reach a reference of type `&'a _`, +/// +/// then 'a must strictly outlive the scope of v. +/// +/// ---- +/// +/// This function is meant to by applied to the type for every +/// expression in the program. +/// +/// ---- +/// +/// (*) The qualifier "simplified" is attached to the above +/// definition of the Drop Check Rule, because it is a simplification +/// of the original Drop Check rule, which attempted to prove that +/// some `Drop` implementations could not possibly access data even if +/// it was technically reachable, due to parametricity. +/// +/// However, (1.) parametricity on its own turned out to be a +/// necessary but insufficient condition, and (2.) future changes to +/// the language are expected to make it impossible to ensure that a +/// `Drop` implementation is actually parametric with respect to any +/// particular type parameter. (In particular, impl specialization is +/// expected to break the needed parametricity property beyond +/// repair.) +/// +/// Therefore, we have scaled back Drop-Check to a more conservative +/// rule that does not attempt to deduce whether a `Drop` +/// implementation could not possible access data of a given lifetime; +/// instead Drop-Check now simply assumes that if a destructor has +/// access (direct or indirect) to a lifetime parameter, then that +/// lifetime must be forced to outlive that destructor's dynamic +/// extent. We then provide the `may_dangle` +/// attribute as a way for destructor implementations to opt-out of +/// this conservative assumption (and thus assume the obligation of +/// ensuring that they do not access data nor invoke methods of +/// values that have been previously dropped). +pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>( rcx: &mut RegionCtxt<'a, 'tcx>, ty: Ty<'tcx>, span: Span, body_id: hir::HirId, + scope: region::Scope, ) -> Result<(), ErrorReported> { - debug!("check_drop_obligations typ: {:?}", ty); + debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}", + ty, scope); + let parent_scope = match rcx.region_scope_tree.opt_encl_scope(scope) { + Some(parent_scope) => parent_scope, + // If no enclosing scope, then it must be the root scope + // which cannot be outlived. + None => return Ok(()), + }; + let parent_scope = rcx.tcx.mk_region(ty::ReScope(parent_scope)); + let origin = || infer::SubregionOrigin::SafeDestructor(span); let cause = &ObligationCause::misc(span, body_id); let infer_ok = rcx.infcx.at(cause, rcx.fcx.param_env).dropck_outlives(ty); debug!("dropck_outlives = {:#?}", infer_ok); - rcx.fcx.register_infer_ok_obligations(infer_ok); - + let kinds = rcx.fcx.register_infer_ok_obligations(infer_ok); + for kind in kinds { + match kind.unpack() { + GenericArgKind::Lifetime(r) => rcx.sub_regions(origin(), parent_scope, r), + GenericArgKind::Type(ty) => rcx.type_must_outlive(origin(), ty, parent_scope), + GenericArgKind::Const(_) => { + // Generic consts don't add constraints. + } + } + } Ok(()) } diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 8668dd99a8cf4..6bed321d27f82 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -18,7 +18,6 @@ use crate::util::nodemap::FxHashMap; use crate::astconv::AstConv as _; use errors::{Applicability, DiagnosticBuilder, pluralise}; -use syntax_pos::hygiene::DesugaringKind; use syntax::ast; use syntax::symbol::{Symbol, kw, sym}; use syntax::source_map::Span; @@ -54,16 +53,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, expr: &'tcx hir::Expr, expected: Ty<'tcx>, - extend_err: impl Fn(&mut DiagnosticBuilder<'_>), ) -> Ty<'tcx> { - self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected), extend_err) + self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected)) } fn check_expr_meets_expectation_or_error( &self, expr: &'tcx hir::Expr, expected: Expectation<'tcx>, - extend_err: impl Fn(&mut DiagnosticBuilder<'_>), ) -> Ty<'tcx> { let expected_ty = expected.to_option(&self).unwrap_or(self.tcx.types.bool); let mut ty = self.check_expr_with_expectation(expr, expected); @@ -87,9 +84,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { - let expr = expr.peel_drop_temps(); - self.suggest_ref_or_into(&mut err, expr, expected_ty, ty); - extend_err(&mut err); + let expr = match &expr.kind { + ExprKind::DropTemps(expr) => expr, + _ => expr, + }; // Error possibly reported in `check_assign` so avoid emitting error again. err.emit_unless(self.is_assign_to_bool(expr, expected_ty)); } @@ -149,20 +147,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(">> type-checking: expr={:?} expected={:?}", expr, expected); - // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block - // without the final expr (e.g. `try { return; }`). We don't want to generate an - // unreachable_code lint for it since warnings for autogenerated code are confusing. - let is_try_block_generated_unit_expr = match expr.kind { - ExprKind::Call(_, ref args) if expr.span.is_desugaring(DesugaringKind::TryBlock) => - args.len() == 1 && args[0].span.is_desugaring(DesugaringKind::TryBlock), - - _ => false, - }; - // Warn for expressions after diverging siblings. - if !is_try_block_generated_unit_expr { - self.warn_if_unreachable(expr.hir_id, expr.span, "expression"); - } + self.warn_if_unreachable(expr.hir_id, expr.span, "expression"); // Hide the outer diverging and has_errors flags. let old_diverges = self.diverges.get(); @@ -175,10 +161,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Warn for non-block expressions with diverging children. match expr.kind { ExprKind::Block(..) | ExprKind::Loop(..) | ExprKind::Match(..) => {}, - // If `expr` is a result of desugaring the try block and is an ok-wrapped - // diverging expression (e.g. it arose from desugaring of `try { return }`), - // we skip issuing a warning because it is autogenerated code. - ExprKind::Call(..) if expr.span.is_desugaring(DesugaringKind::TryBlock) => {}, ExprKind::Call(ref callee, _) => self.warn_if_unreachable(expr.hir_id, callee.span, "call"), ExprKind::MethodCall(_, ref span, _) => @@ -566,17 +548,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the `enclosing_loops` field and let's coerce the // type of `expr_opt` into what is expected. let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); - let ctxt = match enclosing_breakables.opt_find_breakable(target_id) { - Some(ctxt) => ctxt, - None => { // Avoid ICE when `break` is inside a closure (#65383). - self.tcx.sess.delay_span_bug( - expr.span, - "break was outside loop, but no error was emitted", - ); - return tcx.types.err; - } - }; - + let ctxt = enclosing_breakables.find_breakable(target_id); if let Some(ref mut coerce) = ctxt.coerce { if let Some(ref e) = expr_opt { coerce.coerce(self, &cause, e, e_ty); @@ -602,7 +574,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } else { // If `ctxt.coerce` is `None`, we can just ignore - // the type of the expression. This is because + // the type of the expresison. This is because // either this was a break *without* a value, in // which case it is always a legal type (`()`), or // else an error would have been flagged by the @@ -999,7 +971,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: TypeVariableOriginKind::MiscVariable, span: element.span, }); - let element_ty = self.check_expr_has_type_or_error(&element, ty, |_| {}); + let element_ty = self.check_expr_has_type_or_error(&element, ty); (element_ty, ty) } }; @@ -1020,7 +992,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr, ) -> Ty<'tcx> { let flds = expected.only_has_type(self).and_then(|ty| { - let ty = self.resolve_vars_with_obligations(ty); + let ty = self.resolve_type_vars_with_obligations(ty); match ty.kind { ty::Tuple(ref flds) => Some(&flds[..]), _ => None @@ -1086,7 +1058,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the fields with the base_expr. This could cause us to hit errors later // when certain fields are assumed to exist that in fact do not. if !error_happened { - self.check_expr_has_type_or_error(base_expr, adt_ty, |_| {}); + self.check_expr_has_type_or_error(base_expr, adt_ty); match adt_ty.kind { ty::Adt(adt, substs) if adt.is_struct() => { let fru_field_types = adt.non_enum_variant().fields.iter().map(|f| { diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 619768e018c77..d2d3854d2758c 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -14,7 +14,7 @@ use crate::util::nodemap::FxHashMap; struct InteriorVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, - types: FxHashMap, usize>, + types: FxHashMap, usize>, region_scope_tree: &'tcx region::ScopeTree, expr_count: usize, kind: hir::GeneratorKind, @@ -55,7 +55,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { expr_and_pat_count: 0, source: match self.kind { // Guess based on the kind of the current generator. hir::GeneratorKind::Gen => hir::YieldSource::Yield, - hir::GeneratorKind::Async(_) => hir::YieldSource::Await, + hir::GeneratorKind::Async => hir::YieldSource::Await, }, })); @@ -83,12 +83,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { } else { // Map the type to the number of types added before it let entries = self.types.len(); - let scope_span = scope.map(|s| s.span(self.fcx.tcx, self.region_scope_tree)); - self.types.entry(ty::GeneratorInteriorTypeCause { - span: source_span, - ty: &ty, - scope_span - }).or_insert(entries); + self.types.entry(&ty).or_insert(entries); } } else { debug!("no type in expr = {:?}, count = {:?}, span = {:?}", @@ -123,6 +118,9 @@ pub fn resolve_interior<'a, 'tcx>( // Sort types by insertion order types.sort_by_key(|t| t.1); + // Extract type components + let type_list = fcx.tcx.mk_type_list(types.into_iter().map(|t| t.0)); + // The types in the generator interior contain lifetimes local to the generator itself, // which should not be exposed outside of the generator. Therefore, we replace these // lifetimes with existentially-bound lifetimes, which reflect the exact value of the @@ -132,25 +130,18 @@ pub fn resolve_interior<'a, 'tcx>( // if a Sync generator contains an &'α T, we need to check whether &'α T: Sync), // so knowledge of the exact relationships between them isn't particularly important. - debug!("types in generator {:?}, span = {:?}", types, body.value.span); + debug!("types in generator {:?}, span = {:?}", type_list, body.value.span); // Replace all regions inside the generator interior with late bound regions // Note that each region slot in the types gets a new fresh late bound region, // which means that none of the regions inside relate to any other, even if // typeck had previously found constraints that would cause them to be related. let mut counter = 0; - let types = fcx.tcx.fold_regions(&types, &mut false, |_, current_depth| { + let type_list = fcx.tcx.fold_regions(&type_list, &mut false, |_, current_depth| { counter += 1; fcx.tcx.mk_region(ty::ReLateBound(current_depth, ty::BrAnon(counter))) }); - // Store the generator types and spans into the tables for this generator. - let interior_types = types.iter().map(|t| t.0.clone()).collect::>(); - visitor.fcx.inh.tables.borrow_mut().generator_interior_types = interior_types; - - // Extract type components - let type_list = fcx.tcx.mk_type_list(types.into_iter().map(|t| (t.0).ty)); - let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list)); debug!("types in generator after region replacement {:?}, span = {:?}", diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 72a0fe887b964..aeb2c40e2ef83 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -7,7 +7,7 @@ use rustc::ty::subst::Subst; use crate::require_same_types; use rustc_target::spec::abi::Abi; -use syntax::symbol::Symbol; +use syntax::symbol::InternedString; use rustc::hir; @@ -80,7 +80,7 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { /// Remember to add all intrinsics here, in librustc_codegen_llvm/intrinsic.rs, /// and in libcore/intrinsics.rs pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { - let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n))); + let param = |n| tcx.mk_ty_param(n, InternedString::intern(&format!("P{}", n))); let name = it.ident.as_str(); let mk_va_list_ty = |mutbl| { @@ -387,7 +387,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { /// Type-check `extern "platform-intrinsic" { ... }` functions. pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { let param = |n| { - let name = Symbol::intern(&format!("P{}", n)); + let name = InternedString::intern(&format!("P{}", n)); tcx.mk_ty_param(n, name) }; diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 59636d32bc037..9baf06be3f6b5 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -141,24 +141,14 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { /////////////////////////////////////////////////////////////////////////// // ADJUSTMENTS - fn adjust_self_ty( - &mut self, - unadjusted_self_ty: Ty<'tcx>, - pick: &probe::Pick<'tcx>, - ) -> Ty<'tcx> { + fn adjust_self_ty(&mut self, + unadjusted_self_ty: Ty<'tcx>, + pick: &probe::Pick<'tcx>) + -> Ty<'tcx> { // Commit the autoderefs by calling `autoderef` again, but this // time writing the results into the various tables. let mut autoderef = self.autoderef(self.span, unadjusted_self_ty); - let (_, n) = match autoderef.nth(pick.autoderefs) { - Some(n) => n, - None => { - self.tcx.sess.delay_span_bug( - syntax_pos::DUMMY_SP, - &format!("failed autoderef {}", pick.autoderefs), - ); - return self.tcx.types.err; - } - }; + let (_, n) = autoderef.nth(pick.autoderefs).unwrap(); assert_eq!(n, pick.autoderefs); let mut adjustments = autoderef.adjust_steps(self, Needs::None); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index e57cc809c3479..2be311127214d 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -58,7 +58,7 @@ pub enum MethodError<'tcx> { // Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have // forgotten to import a trait. - IllegalSizedBound(Vec, bool), + IllegalSizedBound(Vec), // Found a match, but the return type is wrong BadReturnType, @@ -214,49 +214,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); if result.illegal_sized_bound { - let mut needs_mut = false; - if let ty::Ref(region, t_type, mutability) = self_ty.kind { - let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut { - ty: t_type, - mutbl: mutability.invert(), - }); - // We probe again to see if there might be a borrow mutability discrepancy. - match self.lookup_probe( - span, - segment.ident, - trait_type, - call_expr, - ProbeScope::TraitsInScope - ) { - Ok(ref new_pick) if *new_pick != pick => { - needs_mut = true; - } - _ => {} - } - } - // We probe again, taking all traits into account (not only those in scope). - let candidates = match self.lookup_probe( - span, - segment.ident, - self_ty, - call_expr, - ProbeScope::AllTraits, - ) { - // If we find a different result the caller probably forgot to import a trait. - Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()], - Err(Ambiguity(ref sources)) => sources.iter().filter_map(|source| { - match *source { - // Note: this cannot come from an inherent impl, - // because the first probing succeeded. - ImplSource(def) => self.tcx.trait_id_of_impl(def), - TraitSource(_) => None, + let candidates = + match self.lookup_probe(span, + segment.ident, + self_ty, + call_expr, + ProbeScope::AllTraits) { + + // If we find a different result the caller probably forgot to import a trait. + Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()], + Err(Ambiguity(ref sources)) => { + sources.iter() + .filter_map(|source| { + match *source { + // Note: this cannot come from an inherent impl, + // because the first probing succeeded. + ImplSource(def) => self.tcx.trait_id_of_impl(def), + TraitSource(_) => None, + } + }) + .collect() } - }).collect(), - _ => Vec::new(), - }; + _ => Vec::new(), + }; - return Err(IllegalSizedBound(candidates, needs_mut)); + return Err(IllegalSizedBound(candidates)); } Ok(result.callee) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index d90ed2a790bb6..2d4d2e32f23db 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -461,36 +461,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(span, "this is an associated function, not a method"); } if static_sources.len() == 1 { - let ty_str = if let Some(CandidateSource::ImplSource( - impl_did, - )) = static_sources.get(0) { - // When the "method" is resolved through dereferencing, we really want the - // original type that has the associated function for accurate suggestions. - // (#61411) - let ty = self.impl_self_ty(span, *impl_did).ty; - match (&ty.peel_refs().kind, &actual.peel_refs().kind) { - (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => { - // Use `actual` as it will have more `substs` filled in. - self.ty_to_value_string(actual.peel_refs()) - } - _ => self.ty_to_value_string(ty.peel_refs()), - } - } else { - self.ty_to_value_string(actual.peel_refs()) - }; if let SelfSource::MethodCall(expr) = source { - err.span_suggestion( - expr.span.to(span), - "use associated function syntax instead", - format!("{}::{}", ty_str, item_name), - Applicability::MachineApplicable, - ); + err.span_suggestion(expr.span.to(span), + "use associated function syntax instead", + format!("{}::{}", + self.ty_to_string(actual), + item_name), + Applicability::MachineApplicable); } else { - err.help(&format!( - "try with `{}::{}`", - ty_str, - item_name, - )); + err.help(&format!("try with `{}::{}`", + self.ty_to_string(actual), item_name)); } report_candidates(span, &mut err, static_sources); @@ -538,27 +518,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let mut fallback_span = true; - let msg = "remove this method call"; - if item_name.as_str() == "as_str" && actual.peel_refs().is_str() { - if let SelfSource::MethodCall(expr) = source { - let call_expr = self.tcx.hir().expect_expr( - self.tcx.hir().get_parent_node(expr.hir_id), - ); - if let Some(span) = call_expr.span.trim_start(expr.span) { - err.span_suggestion( - span, - msg, - String::new(), - Applicability::MachineApplicable, - ); - fallback_span = false; - } - } - if fallback_span { - err.span_label(span, msg); - } - } else if let Some(lev_candidate) = lev_candidate { + if let Some(lev_candidate) = lev_candidate { let def_kind = lev_candidate.def_kind(); err.span_suggestion( span, @@ -593,33 +553,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); } - MethodError::IllegalSizedBound(candidates, needs_mut) => { + MethodError::IllegalSizedBound(candidates) => { let msg = format!("the `{}` method cannot be invoked on a trait object", item_name); let mut err = self.sess().struct_span_err(span, &msg); if !candidates.is_empty() { - let help = format!( - "{an}other candidate{s} {were} found in the following trait{s}, perhaps \ - add a `use` for {one_of_them}:", - an = if candidates.len() == 1 {"an" } else { "" }, - s = pluralise!(candidates.len()), - were = if candidates.len() == 1 { "was" } else { "were" }, - one_of_them = if candidates.len() == 1 { - "it" - } else { - "one_of_them" - }, - ); + let help = format!("{an}other candidate{s} {were} found in the following \ + trait{s}, perhaps add a `use` for {one_of_them}:", + an = if candidates.len() == 1 {"an" } else { "" }, + s = pluralise!(candidates.len()), + were = if candidates.len() == 1 { "was" } else { "were" }, + one_of_them = if candidates.len() == 1 { + "it" + } else { + "one_of_them" + }); self.suggest_use_candidates(&mut err, help, candidates); } - if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind { - if needs_mut { - let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut { - ty: t_type, - mutbl: mutability.invert(), - }); - err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty)); - } - } err.emit(); } @@ -630,14 +579,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } - /// Print out the type for use in value namespace. - fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String { - match ty.kind { - ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)), - _ => self.ty_to_string(ty), - } - } - fn suggest_use_candidates(&self, err: &mut DiagnosticBuilder<'_>, mut msg: String, @@ -690,30 +631,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn suggest_valid_traits( - &self, - err: &mut DiagnosticBuilder<'_>, - valid_out_of_scope_traits: Vec, - ) -> bool { + fn suggest_valid_traits(&self, + err: &mut DiagnosticBuilder<'_>, + valid_out_of_scope_traits: Vec) -> bool { if !valid_out_of_scope_traits.is_empty() { let mut candidates = valid_out_of_scope_traits; candidates.sort(); candidates.dedup(); err.help("items from traits can only be used if the trait is in scope"); - let msg = format!( - "the following {traits_are} implemented but not in scope; \ - perhaps add a `use` for {one_of_them}:", - traits_are = if candidates.len() == 1 { - "trait is" - } else { - "traits are" - }, - one_of_them = if candidates.len() == 1 { - "it" - } else { - "one of them" - }, - ); + let msg = format!("the following {traits_are} implemented but not in scope, \ + perhaps add a `use` for {one_of_them}:", + traits_are = if candidates.len() == 1 { + "trait is" + } else { + "traits are" + }, + one_of_them = if candidates.len() == 1 { + "it" + } else { + "one of them" + }); self.suggest_use_candidates(err, msg, candidates); true @@ -777,7 +714,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { "items from traits can only be used if the trait is implemented and in scope" }); - let message = |action| format!( + let mut msg = format!( "the following {traits_define} an item `{name}`, perhaps you need to {action} \ {one_of_them}:", traits_define = if candidates.len() == 1 { @@ -785,7 +722,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { "traits define" }, - action = action, + action = if let Some(param) = param_type { + format!("restrict type parameter `{}` with", param) + } else { + "implement".to_string() + }, one_of_them = if candidates.len() == 1 { "it" } else { @@ -805,81 +746,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Get the `hir::Param` to verify whether it already has any bounds. // We do this to avoid suggesting code that ends up as `T: FooBar`, // instead we suggest `T: Foo + Bar` in that case. - match hir.get(id) { - Node::GenericParam(ref param) => { - let mut impl_trait = false; - let has_bounds = if let hir::GenericParamKind::Type { - synthetic: Some(_), .. - } = ¶m.kind { + let mut has_bounds = false; + let mut impl_trait = false; + if let Node::GenericParam(ref param) = hir.get(id) { + match param.kind { + hir::GenericParamKind::Type { synthetic: Some(_), .. } => { // We've found `fn foo(x: impl Trait)` instead of // `fn foo(x: T)`. We want to suggest the correct // `fn foo(x: impl Trait + TraitBound)` instead of // `fn foo(x: T)`. (#63706) impl_trait = true; - param.bounds.get(1) - } else { - param.bounds.get(0) - }; - let sp = hir.span(id); - let sp = if let Some(first_bound) = has_bounds { - // `sp` only covers `T`, change it so that it covers - // `T:` when appropriate - sp.until(first_bound.span()) - } else { - sp - }; - // FIXME: contrast `t.def_id` against `param.bounds` to not suggest - // traits already there. That can happen when the cause is that - // we're in a const scope or associated function used as a method. - err.span_suggestions( - sp, - &message(format!( - "restrict type parameter `{}` with", - param.name.ident().as_str(), - )), - candidates.iter().map(|t| format!( - "{}{} {}{}", - param.name.ident().as_str(), - if impl_trait { " +" } else { ":" }, - self.tcx.def_path_str(t.def_id), - if has_bounds.is_some() { " + "} else { "" }, - )), - Applicability::MaybeIncorrect, - ); - suggested = true; - } - Node::Item(hir::Item { - kind: hir::ItemKind::Trait(.., bounds, _), ident, .. - }) => { - let (sp, sep, article) = if bounds.is_empty() { - (ident.span.shrink_to_hi(), ":", "a") - } else { - (bounds.last().unwrap().span().shrink_to_hi(), " +", "another") - }; - err.span_suggestions( - sp, - &message(format!("add {} supertrait for", article)), - candidates.iter().map(|t| format!( - "{} {}", - sep, - self.tcx.def_path_str(t.def_id), - )), - Applicability::MaybeIncorrect, - ); - suggested = true; + has_bounds = param.bounds.len() > 1; + } + _ => { + has_bounds = !param.bounds.is_empty(); + } } - _ => {} } + let sp = hir.span(id); + // `sp` only covers `T`, change it so that it covers + // `T:` when appropriate + let sp = if has_bounds { + sp.to(self.tcx + .sess + .source_map() + .next_point(self.tcx.sess.source_map().next_point(sp))) + } else { + sp + }; + + // FIXME: contrast `t.def_id` against `param.bounds` to not suggest traits + // already there. That can happen when the cause is that we're in a const + // scope or associated function used as a method. + err.span_suggestions( + sp, + &msg[..], + candidates.iter().map(|t| format!( + "{}{} {}{}", + param, + if impl_trait { " +" } else { ":" }, + self.tcx.def_path_str(t.def_id), + if has_bounds { " +"} else { "" }, + )), + Applicability::MaybeIncorrect, + ); + suggested = true; } }; } if !suggested { - let mut msg = message(if let Some(param) = param_type { - format!("restrict type parameter `{}` with", param) - } else { - "implement".to_string() - }); for (i, trait_info) in candidates.iter().enumerate() { msg.push_str(&format!( "\ncandidate #{}: `{}`", @@ -919,7 +835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This occurs for UFCS desugaring of `T::method`, where there is no // receiver expression for the method call, and thus no autoderef. if let SelfSource::QPath(_) = source { - return is_local(self.resolve_vars_with_obligations(rcvr_ty)); + return is_local(self.resolve_type_vars_with_obligations(rcvr_ty)); } self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty)) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 96a097695fa1f..9f2c991fdd236 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -99,7 +99,7 @@ use crate::middle::lang_items; use crate::namespace::Namespace; use rustc::infer::{self, InferCtxt, InferOk, InferResult}; use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use rustc_target::spec::abi::Abi; use rustc::infer::opaque_types::OpaqueTypeDecl; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -128,7 +128,6 @@ use syntax::attr; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::source_map::{DUMMY_SP, original_sp}; use syntax::symbol::{kw, sym}; -use syntax::util::parser::ExprPrecedence; use std::cell::{Cell, RefCell, Ref, RefMut}; use std::collections::hash_map::Entry; @@ -473,7 +472,7 @@ pub enum Diverges { WarnedAlways } -// Convenience impls for combining `Diverges`. +// Convenience impls for combinig `Diverges`. impl ops::BitAnd for Diverges { type Output = Self; @@ -536,16 +535,10 @@ pub struct EnclosingBreakables<'tcx> { impl<'tcx> EnclosingBreakables<'tcx> { fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> { - self.opt_find_breakable(target_id).unwrap_or_else(|| { + let ix = *self.by_id.get(&target_id).unwrap_or_else(|| { bug!("could not find enclosing breakable with id {}", target_id); - }) - } - - fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> { - match self.by_id.get(&target_id) { - Some(ix) => Some(&mut self.stack[*ix]), - None => None, - } + }); + &mut self.stack[ix] } } @@ -568,19 +561,7 @@ pub struct FnCtxt<'a, 'tcx> { // if type checking is run in parallel. err_count_on_creation: usize, - /// If `Some`, this stores coercion information for returned - /// expressions. If `None`, this is in a context where return is - /// inappropriate, such as a const expression. - /// - /// This is a `RefCell`, which means that we - /// can track all the return expressions and then use them to - /// compute a useful coercion from the set, similar to a match - /// expression or other branching context. You can use methods - /// like `expected_ty` to access the declared return type (if - /// any). ret_coercion: Option>>, - - /// First span of a return site that we find. Used in error messages. ret_coercion_span: RefCell>, yield_ty: Option>, @@ -1151,29 +1132,8 @@ fn check_fn<'a, 'tcx>( let outer_hir_id = fcx.tcx.hir().as_local_hir_id(outer_def_id).unwrap(); GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id, }.visit_body(body); - // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` - // (as it's created inside the body itself, not passed in from outside). - let maybe_va_list = if fn_sig.c_variadic { - let va_list_did = fcx.tcx.require_lang_item( - lang_items::VaListTypeLangItem, - Some(body.params.last().unwrap().span), - ); - let region = fcx.tcx.mk_region(ty::ReScope(region::Scope { - id: body.value.hir_id.local_id, - data: region::ScopeData::CallSite - })); - - Some(fcx.tcx.type_of(va_list_did).subst(fcx.tcx, &[region.into()])) - } else { - None - }; - // Add formal parameters. - for (param_ty, param) in - fn_sig.inputs().iter().copied() - .chain(maybe_va_list) - .zip(&body.params) - { + for (param_ty, param) in fn_sig.inputs().iter().zip(&body.params) { // Check the pattern. fcx.check_pat_top(¶m.pat, param_ty, None); @@ -1393,37 +1353,9 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) { def.destructor(tcx); // force the destructor to be evaluated check_representable(tcx, span, def_id); check_transparent(tcx, span, def_id); - check_union_fields(tcx, span, def_id); check_packed(tcx, span, def_id); } -/// When the `#![feature(untagged_unions)]` gate is active, -/// check that the fields of the `union` does not contain fields that need dropping. -fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: DefId) -> bool { - let item_type = tcx.type_of(item_def_id); - if let ty::Adt(def, substs) = item_type.kind { - assert!(def.is_union()); - let fields = &def.non_enum_variant().fields; - for field in fields { - let field_ty = field.ty(tcx, substs); - // We are currently checking the type this field came from, so it must be local. - let field_span = tcx.hir().span_if_local(field.did).unwrap(); - let param_env = tcx.param_env(field.did); - if field_ty.needs_drop(tcx, param_env) { - struct_span_err!(tcx.sess, field_span, E0740, - "unions may not contain fields that need dropping") - .span_note(field_span, - "`std::mem::ManuallyDrop` can be used to wrap the type") - .emit(); - return false; - } - } - } else { - span_bug!(span, "unions must be ty::Adt, but got {:?}", item_type.kind); - } - return true; -} - /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo` /// projections that would result in "inheriting lifetimes". fn check_opaque<'tcx>( @@ -1747,6 +1679,8 @@ fn check_specialization_validity<'tcx>( impl_id: DefId, impl_item: &hir::ImplItem, ) { + let ancestors = trait_def.ancestors(tcx, impl_id); + let kind = match impl_item.kind { hir::ImplItemKind::Const(..) => ty::AssocKind::Const, hir::ImplItemKind::Method(..) => ty::AssocKind::Method, @@ -1754,53 +1688,15 @@ fn check_specialization_validity<'tcx>( hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type, }; - let mut ancestor_impls = trait_def.ancestors(tcx, impl_id) - .skip(1) - .filter_map(|parent| { - if parent.is_from_trait() { - None - } else { - Some((parent, parent.item(tcx, trait_item.ident, kind, trait_def.def_id))) - } - }) - .peekable(); + let parent = ancestors.defs(tcx, trait_item.ident, kind, trait_def.def_id).nth(1) + .map(|node_item| node_item.map(|parent| parent.defaultness)); - if ancestor_impls.peek().is_none() { - // No parent, nothing to specialize. - return; - } - - let opt_result = ancestor_impls.find_map(|(parent_impl, parent_item)| { - match parent_item { - // Parent impl exists, and contains the parent item we're trying to specialize, but - // doesn't mark it `default`. - Some(parent_item) if tcx.impl_item_is_final(&parent_item) => { - Some(Err(parent_impl.def_id())) - } - - // Parent impl contains item and makes it specializable. - Some(_) => { - Some(Ok(())) - } - - // Parent impl doesn't mention the item. This means it's inherited from the - // grandparent. In that case, if parent is a `default impl`, inherited items use the - // "defaultness" from the grandparent, else they are final. - None => if tcx.impl_is_default(parent_impl.def_id()) { - None - } else { - Some(Err(parent_impl.def_id())) - } + if let Some(parent) = parent { + if tcx.impl_item_is_final(&parent) { + report_forbidden_specialization(tcx, impl_item, parent.node.def_id()); } - }); - - // If `opt_result` is `None`, we have only encoutered `default impl`s that don't contain the - // item. This is allowed, the item isn't actually getting specialized here. - let result = opt_result.unwrap_or(Ok(())); - - if let Err(parent_impl) = result { - report_forbidden_specialization(tcx, impl_item, parent_impl); } + } fn check_impl_items_against_trait<'tcx>( @@ -1916,7 +1812,8 @@ fn check_impl_items_against_trait<'tcx>( let associated_type_overridden = overridden_associated_type.is_some(); for trait_item in tcx.associated_items(impl_trait_ref.def_id) { let is_implemented = trait_def.ancestors(tcx, impl_id) - .leaf_def(tcx, trait_item.ident, trait_item.kind) + .defs(tcx, trait_item.ident, trait_item.kind, impl_trait_ref.def_id) + .next() .map(|node_item| !node_item.node.is_from_trait()) .unwrap_or(false); @@ -2279,17 +2176,19 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { self.tcx } - fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> { + fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) + -> &'tcx ty::GenericPredicates<'tcx> + { let tcx = self.tcx; let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); let item_id = tcx.hir().ty_param_owner(hir_id); let item_def_id = tcx.hir().local_def_id(item_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; - ty::GenericPredicates { + tcx.arena.alloc(ty::GenericPredicates { parent: None, - predicates: tcx.arena.alloc_from_iter( - self.param_env.caller_bounds.iter().filter_map(|&predicate| match predicate { + predicates: self.param_env.caller_bounds.iter().filter_map(|&predicate| { + match predicate { ty::Predicate::Trait(ref data) if data.skip_binder().self_ty().is_param(index) => { // HACK(eddyb) should get the original `Span`. @@ -2297,9 +2196,9 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { Some((predicate, span)) } _ => None - }), - ), - } + } + }).collect() + }) } fn re_infer( @@ -2444,8 +2343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // which diverges, that we are about to lint on. This gives suboptimal diagnostics. // Instead, stop here so that the `if`- or `while`-expression's block is linted instead. if !span.is_desugaring(DesugaringKind::CondTemporary) && - !span.is_desugaring(DesugaringKind::Async) && - !orig_span.is_desugaring(DesugaringKind::Await) + !span.is_desugaring(DesugaringKind::Async) { self.diverges.set(Diverges::WarnedAlways); @@ -2474,23 +2372,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.cause(span, ObligationCauseCode::MiscObligation) } - /// Resolves type and const variables in `ty` if possible. Unlike the infcx + /// Resolves type variables in `ty` if possible. Unlike the infcx /// version (resolve_vars_if_possible), this version will /// also select obligations if it seems useful, in an effort /// to get more type information. - fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> { - debug!("resolve_vars_with_obligations(ty={:?})", ty); + fn resolve_type_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> { + debug!("resolve_type_vars_with_obligations(ty={:?})", ty); // No Infer()? Nothing needs doing. - if !ty.has_infer_types() && !ty.has_infer_consts() { - debug!("resolve_vars_with_obligations: ty={:?}", ty); + if !ty.has_infer_types() { + debug!("resolve_type_vars_with_obligations: ty={:?}", ty); return ty; } // If `ty` is a type variable, see whether we already know what it is. ty = self.resolve_vars_if_possible(&ty); - if !ty.has_infer_types() && !ty.has_infer_consts() { - debug!("resolve_vars_with_obligations: ty={:?}", ty); + if !ty.has_infer_types() { + debug!("resolve_type_vars_with_obligations: ty={:?}", ty); return ty; } @@ -2501,7 +2399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.select_obligations_where_possible(false, |_| {}); ty = self.resolve_vars_if_possible(&ty); - debug!("resolve_vars_with_obligations: ty={:?}", ty); + debug!("resolve_type_vars_with_obligations: ty={:?}", ty); ty } @@ -2767,7 +2665,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut opaque_types = self.opaque_types.borrow_mut(); for (ty, decl) in opaque_type_map { - let _ = opaque_types.insert(ty, decl); + let old_value = opaque_types.insert(ty, decl); + assert!(old_value.is_none(), "instantiated twice: {:?}/{:?}", ty, decl); } value @@ -3701,7 +3600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { formal_ret: Ty<'tcx>, formal_args: &[Ty<'tcx>]) -> Vec> { - let formal_ret = self.resolve_vars_with_obligations(formal_ret); + let formal_ret = self.resolve_type_vars_with_obligations(formal_ret); let ret_ty = match expected_ret.only_has_type(self) { Some(ret) => ret, None => return Vec::new() @@ -3959,15 +3858,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn suggest_semicolon_at_end(&self, span: Span, err: &mut DiagnosticBuilder<'_>) { - err.span_suggestion_short( - span.shrink_to_hi(), - "consider using a semicolon here", - ";".to_string(), - Applicability::MachineApplicable, - ); - } - pub fn check_stmt(&self, stmt: &'tcx hir::Stmt) { // Don't do all the complex logic below for `DeclItem`. match stmt.kind { @@ -3991,10 +3881,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::StmtKind::Item(_) => {} hir::StmtKind::Expr(ref expr) => { // Check with expected type of `()`. - - self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit(), |err| { - self.suggest_semicolon_at_end(expr.span, err); - }); + self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit()); } hir::StmtKind::Semi(ref expr) => { self.check_expr(&expr); @@ -4247,21 +4134,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn suggest_mismatched_types_on_tail( &self, err: &mut DiagnosticBuilder<'tcx>, - expr: &'tcx hir::Expr, + expression: &'tcx hir::Expr, expected: Ty<'tcx>, found: Ty<'tcx>, cause_span: Span, blk_id: hir::HirId, ) -> bool { - let expr = expr.peel_drop_temps(); - self.suggest_missing_semicolon(err, expr, expected, cause_span); + self.suggest_missing_semicolon(err, expression, expected, cause_span); let mut pointing_at_return_type = false; if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { pointing_at_return_type = self.suggest_missing_return_type( err, &fn_decl, expected, found, can_suggest); } - self.suggest_ref_or_into(err, expr, expected, found); - self.suggest_boxing_when_appropriate(err, expr, expected, found); + self.suggest_ref_or_into(err, expression, expected, found); + self.suggest_boxing_when_appropriate(err, expression, expected, found); pointing_at_return_type } @@ -4284,7 +4170,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Closure(def_id, substs) => { // We don't use `closure_sig` to account for malformed closures like // `|_: [_; continue]| {}` and instead we don't suggest anything. - let closure_sig_ty = substs.as_closure().sig_ty(def_id, self.tcx); + let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx); (def_id, match closure_sig_ty.kind { ty::FnPtr(sig) => sig, _ => return false, @@ -4425,11 +4311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let max_len = receiver.rfind(".").unwrap(); format!("{}{}", &receiver[..max_len], method_call) } else { - if expr.precedence().order() < ExprPrecedence::MethodCall.order() { - format!("({}){}", receiver, method_call) - } else { - format!("{}{}", receiver, method_call) - } + format!("{}{}", receiver, method_call) }; Some(if is_struct_pat_shorthand_field { format!("{}: {}", receiver, sugg) @@ -4550,7 +4432,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion( span, "try adding a return type", - format!("-> {} ", self.resolve_vars_with_obligations(found)), + format!("-> {} ", self.resolve_type_vars_with_obligations(found)), Applicability::MachineApplicable); true } @@ -4613,7 +4495,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let item_id = self.tcx().hir().get_parent_node(self.body_id); if let Some(body_id) = self.tcx().hir().maybe_body_owned_by(item_id) { let body = self.tcx().hir().body(body_id); - if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind { + if let Some(hir::GeneratorKind::Async) = body.generator_kind { let sp = expr.span; // Check for `Future` implementations by constructing a predicate to // prove: `::Output == U` @@ -5026,7 +4908,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If no resolution is possible, then an error is reported. // Numeric inference variables may be left unresolved. pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { - let ty = self.resolve_vars_with_obligations(ty); + let ty = self.resolve_type_vars_with_obligations(ty); if !ty.is_ty_var() { ty } else { diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 819c347d3ae95..f9df2d1d848ff 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -179,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_expr_with_needs(lhs_expr, Needs::MutPlace) } }; - let lhs_ty = self.resolve_vars_with_obligations(lhs_ty); + let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty); // N.B., as we have not yet type-checked the RHS, we don't have the // type at hand. Make a variable to represent it. The whole reason @@ -196,7 +196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // see `NB` above let rhs_ty = self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var); - let rhs_ty = self.resolve_vars_with_obligations(rhs_ty); + let rhs_ty = self.resolve_type_vars_with_obligations(rhs_ty); let return_ty = match result { Ok(method) => { diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 97c30f208f5ec..53ee0777c7c1d 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -251,7 +251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, mut def_bm: BindingMode, ) -> (Ty<'tcx>, BindingMode) { - let mut expected = self.resolve_vars_with_obligations(&expected); + let mut expected = self.resolve_type_vars_with_obligations(&expected); // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example, // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 2f9091282b707..90407780a302d 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -347,7 +347,13 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { ); self.outlives_environment .save_implied_bounds(body_id.hir_id); - self.link_fn_params(&body.params); + self.link_fn_params( + region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::Node, + }, + &body.params, + ); self.visit_body(body); self.visit_region_obligations(body_id.hir_id); @@ -424,8 +430,8 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { let typ = self.resolve_node_type(hir_id); let body_id = self.body_id; - let _ = dropck::check_drop_obligations( - self, typ, span, body_id, + let _ = dropck::check_safety_of_destructor_if_necessary( + self, typ, span, body_id, var_scope, ); }) } @@ -922,15 +928,29 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { } fn check_safety_of_rvalue_destructor_if_necessary(&mut self, cmt: &mc::cmt_<'tcx>, span: Span) { - if let Categorization::Rvalue = cmt.cat { - let typ = self.resolve_type(cmt.ty); - let body_id = self.body_id; - let _ = dropck::check_drop_obligations( - self, - typ, - span, - body_id, - ); + if let Categorization::Rvalue(region) = cmt.cat { + match *region { + ty::ReScope(rvalue_scope) => { + let typ = self.resolve_type(cmt.ty); + let body_id = self.body_id; + let _ = dropck::check_safety_of_destructor_if_necessary( + self, + typ, + span, + body_id, + rvalue_scope, + ); + } + ty::ReStatic => {} + _ => { + span_bug!( + span, + "unexpected rvalue region in rvalue \ + destructor safety checking: `{:?}`", + region + ); + } + } } } @@ -1054,11 +1074,13 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { /// Computes the guarantors for any ref bindings in a match and /// then ensures that the lifetime of the resulting pointer is /// linked to the lifetime of its guarantor (if any). - fn link_fn_params(&self, params: &[hir::Param]) { + fn link_fn_params(&self, body_scope: region::Scope, params: &[hir::Param]) { + debug!("regionck::link_fn_params(body_scope={:?})", body_scope); for param in params { let param_ty = self.node_ty(param.hir_id); + let re_scope = self.tcx.mk_region(ty::ReScope(body_scope)); let param_cmt = self.with_mc(|mc| { - Rc::new(mc.cat_rvalue(param.hir_id, param.pat.span, param_ty)) + Rc::new(mc.cat_rvalue(param.hir_id, param.pat.span, re_scope, param_ty)) }); debug!("param_ty={:?} param_cmt={:?} param={:?}", param_ty, param_cmt, param); self.link_pattern(param_cmt, ¶m.pat); @@ -1200,8 +1222,8 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { | Categorization::StaticItem | Categorization::Upvar(..) | Categorization::Local(..) - | Categorization::ThreadLocal - | Categorization::Rvalue => { + | Categorization::ThreadLocal(..) + | Categorization::Rvalue(..) => { // These are all "base cases" with independent lifetimes // that are not subject to inference return; diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 97e59664df0c0..71ea938a8039b 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -96,10 +96,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Extract the type of the closure. let ty = self.node_ty(closure_hir_id); let (closure_def_id, substs) = match ty.kind { - ty::Closure(def_id, substs) => ( - def_id, - UpvarSubsts::Closure(substs) - ), + ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)), ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)), ty::Error => { // #51714: skip analysis when we have already encountered type errors @@ -193,8 +190,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Unify the (as yet unbound) type variable in the closure // substs with the kind we inferred. let inferred_kind = delegate.current_closure_kind; - let closure_kind_ty = closure_substs - .as_closure().kind_ty(closure_def_id, self.tcx); + let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx); self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty); // If we have an origin, store it. @@ -325,7 +321,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { euv::Copy => { return; } - euv::Move => {} + euv::Move(_) => {} } let tcx = self.fcx.tcx; @@ -412,8 +408,8 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { Categorization::Deref(_, mc::UnsafePtr(..)) | Categorization::StaticItem - | Categorization::ThreadLocal - | Categorization::Rvalue + | Categorization::ThreadLocal(..) + | Categorization::Rvalue(..) | Categorization::Local(_) | Categorization::Upvar(..) => { return; @@ -443,8 +439,8 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { Categorization::Deref(_, mc::UnsafePtr(..)) | Categorization::StaticItem - | Categorization::ThreadLocal - | Categorization::Rvalue + | Categorization::ThreadLocal(..) + | Categorization::Rvalue(..) | Categorization::Local(_) | Categorization::Upvar(..) => {} } @@ -586,13 +582,48 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { } impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { - fn consume(&mut self, cmt: &mc::cmt_<'tcx>,mode: euv::ConsumeMode) { + fn consume( + &mut self, + _consume_id: hir::HirId, + _consume_span: Span, + cmt: &mc::cmt_<'tcx>, + mode: euv::ConsumeMode, + ) { debug!("consume(cmt={:?},mode={:?})", cmt, mode); self.adjust_upvar_borrow_kind_for_consume(cmt, mode); } - fn borrow(&mut self, cmt: &mc::cmt_<'tcx>, bk: ty::BorrowKind) { - debug!("borrow(cmt={:?}, bk={:?})", cmt, bk); + fn matched_pat( + &mut self, + _matched_pat: &hir::Pat, + _cmt: &mc::cmt_<'tcx>, + _mode: euv::MatchMode, + ) { + } + + fn consume_pat( + &mut self, + _consume_pat: &hir::Pat, + cmt: &mc::cmt_<'tcx>, + mode: euv::ConsumeMode, + ) { + debug!("consume_pat(cmt={:?},mode={:?})", cmt, mode); + self.adjust_upvar_borrow_kind_for_consume(cmt, mode); + } + + fn borrow( + &mut self, + borrow_id: hir::HirId, + _borrow_span: Span, + cmt: &mc::cmt_<'tcx>, + _loan_region: ty::Region<'tcx>, + bk: ty::BorrowKind, + _loan_cause: euv::LoanCause, + ) { + debug!( + "borrow(borrow_id={}, cmt={:?}, bk={:?})", + borrow_id, cmt, bk + ); match bk { ty::ImmBorrow => {} @@ -605,7 +636,15 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { } } - fn mutate(&mut self, assignee_cmt: &mc::cmt_<'tcx>) { + fn decl_without_init(&mut self, _id: hir::HirId, _span: Span) {} + + fn mutate( + &mut self, + _assignment_id: hir::HirId, + _assignment_span: Span, + assignee_cmt: &mc::cmt_<'tcx>, + _mode: euv::MutateMode, + ) { debug!("mutate(assignee_cmt={:?})", assignee_cmt); self.adjust_upvar_borrow_kind_for_mut(assignee_cmt); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 18b103960c745..20c517d779b42 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -172,18 +172,6 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) { _ => None }; check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig); - - // Prohibits applying `#[track_caller]` to trait decls - for attr in &trait_item.attrs { - if attr.check_name(sym::track_caller) { - struct_span_err!( - tcx.sess, - attr.span, - E0738, - "`#[track_caller]` is not supported in trait declarations." - ).emit(); - } - } } pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) { @@ -194,30 +182,6 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) { hir::ImplItemKind::Method(ref sig, _) => Some(sig), _ => None }; - - // Prohibits applying `#[track_caller]` to trait impls - if method_sig.is_some() { - let track_caller_attr = impl_item.attrs.iter() - .find(|a| a.check_name(sym::track_caller)); - if let Some(tc_attr) = track_caller_attr { - let parent_hir_id = tcx.hir().get_parent_item(hir_id); - let containing_item = tcx.hir().expect_item(parent_hir_id); - let containing_impl_is_for_trait = match &containing_item.kind { - hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr.is_some(), - _ => bug!("parent of an ImplItem must be an Impl"), - }; - - if containing_impl_is_for_trait { - struct_span_err!( - tcx.sess, - tc_attr.span, - E0738, - "`#[track_caller]` is not supported in traits yet." - ).emit(); - } - } - } - check_associated_item(tcx, impl_item.hir_id, impl_item.span, method_sig); } @@ -791,7 +755,7 @@ fn check_opaque_types<'fcx, 'tcx>( "check_opaque_types: may define, predicates={:#?}", predicates, ); - for &(pred, _) in predicates.predicates { + for &(pred, _) in predicates.predicates.iter() { let substituted_pred = pred.subst(fcx.tcx, substs); // Avoid duplication of predicates that contain no parameters, for example. if !predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) { @@ -1011,7 +975,7 @@ fn check_variances_for_type_defn<'tcx>( identify_constrained_generic_params( tcx, - ty_predicates, + &ty_predicates, None, &mut constrained_parameters, ); @@ -1035,16 +999,11 @@ fn report_bivariance(tcx: TyCtxt<'_>, span: Span, param_name: ast::Name) { let suggested_marker_id = tcx.lang_items().phantom_data(); // Help is available only in presence of lang items. - let msg = if let Some(def_id) = suggested_marker_id { - format!( - "consider removing `{}`, referring to it in a field, or using a marker such as `{}`", - param_name, - tcx.def_path_str(def_id), - ) - } else { - format!( "consider removing `{}` or referring to it in a field", param_name) - }; - err.help(&msg); + if let Some(def_id) = suggested_marker_id { + err.help(&format!("consider removing `{}` or using a marker such as `{}`", + param_name, + tcx.def_path_str(def_id))); + } err.emit(); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 7a8a209a5350c..de78c1cdfaba3 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -58,7 +58,6 @@ 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, @@ -190,26 +189,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { if let hir::ExprKind::Index(ref base, ref index) = e.kind { let mut tables = self.fcx.tables.borrow_mut(); - // All valid indexing looks like this; might encounter non-valid indexes at this point. - let base_ty = tables.expr_ty_adjusted_opt(&base).map(|t| &t.kind); - if base_ty.is_none() { - // When encountering `return [0][0]` outside of a `fn` body we can encounter a base - // that isn't in the type table. We assume more relevant errors have already been - // emitted, so we delay an ICE if none have. (#64638) - self.tcx().sess.delay_span_bug(e.span, &format!("bad base: `{:?}`", base)); - } - if let Some(ty::Ref(_, base_ty, _)) = base_ty { - let index_ty = tables.expr_ty_adjusted_opt(&index).unwrap_or_else(|| { - // When encountering `return [0][0]` outside of a `fn` body we would attempt - // to access an unexistend index. We assume that more relevant errors will - // already have been emitted, so we only gate on this with an ICE if no - // error has been emitted. (#64638) - self.tcx().sess.delay_span_bug( - e.span, - &format!("bad index {:?} for base: `{:?}`", index, base), - ); - self.fcx.tcx.types.err - }); + // All valid indexing looks like this; might encounter non-valid indexes at this point + if let ty::Ref(_, base_ty, _) = tables.expr_ty_adjusted(&base).kind { + let index_ty = tables.expr_ty_adjusted(&index); let index_ty = self.fcx.resolve_vars_if_possible(&index_ty); if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize { @@ -448,12 +430,6 @@ 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/mod.rs b/src/librustc_typeck/coherence/mod.rs index 8adf4bb94a898..a44c475e0f8a9 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -183,11 +183,8 @@ fn check_impl_overlap<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId) { for component_def_id in component_def_ids { if !tcx.is_object_safe(component_def_id) { - // Without the 'object_safe_for_dispatch' feature this is an error - // which will be reported by wfcheck. Ignore it here. + // This is an error, but it will be reported by wfcheck. Ignore it here. // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. - // With the feature enabled, the trait is not implemented automatically, - // so this is valid. } else { let mut supertrait_def_ids = traits::supertrait_def_ids(tcx, component_def_id); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 00435d67184a3..8c3d6357f0bbf 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -36,7 +36,7 @@ use syntax::ast; use syntax::ast::{Ident, MetaItemKind}; use syntax::attr::{InlineAttr, OptimizeAttr, list_contains_name, mark_used}; use syntax::feature_gate; -use syntax::symbol::{kw, Symbol, sym}; +use syntax::symbol::{InternedString, kw, Symbol, sym}; use syntax_pos::{Span, DUMMY_SP}; use rustc::hir::def::{CtorKind, Res, DefKind}; @@ -182,7 +182,8 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { self.tcx } - fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> { + fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) + -> &'tcx ty::GenericPredicates<'tcx> { self.tcx .at(span) .type_param_predicates((self.item_def_id, def_id)) @@ -253,7 +254,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { fn type_param_predicates( tcx: TyCtxt<'_>, (item_def_id, def_id): (DefId, DefId), -) -> ty::GenericPredicates<'_> { +) -> &ty::GenericPredicates<'_> { use rustc::hir::*; // In the AST, bounds can derive from two places. Either @@ -265,7 +266,7 @@ fn type_param_predicates( let param_owner_def_id = tcx.hir().local_def_id(param_owner); let generics = tcx.generics_of(param_owner_def_id); let index = generics.param_def_id_to_index[&def_id]; - let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(param_id)); + let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(param_id).as_interned_str()); // Don't look for bounds where the type parameter isn't in scope. let parent = if item_def_id == param_owner_def_id { @@ -274,10 +275,10 @@ fn type_param_predicates( tcx.generics_of(item_def_id).parent }; - let mut result = parent.map(|parent| { + let result = parent.map_or(&tcx.common.empty_predicates, |parent| { let icx = ItemCtxt::new(tcx, parent); icx.get_type_parameter_bounds(DUMMY_SP, def_id) - }).unwrap_or_default(); + }); let mut extend = None; let item_hir_id = tcx.hir().as_local_hir_id(item_def_id).unwrap(); @@ -320,7 +321,9 @@ fn type_param_predicates( }; let icx = ItemCtxt::new(tcx, item_def_id); - let extra_predicates = extend.into_iter().chain( + let mut result = (*result).clone(); + result.predicates.extend(extend.into_iter()); + result.predicates.extend( icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true)) .into_iter() .filter(|(predicate, _)| { @@ -328,12 +331,9 @@ fn type_param_predicates( ty::Predicate::Trait(ref data) => data.skip_binder().self_ty().is_param(index), _ => false, } - }), - ); - result.predicates = tcx.arena.alloc_from_iter( - result.predicates.iter().copied().chain(extra_predicates), + }) ); - result + tcx.arena.alloc(result) } impl ItemCtxt<'tcx> { @@ -698,7 +698,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef { fn super_predicates_of( tcx: TyCtxt<'_>, trait_def_id: DefId, -) -> ty::GenericPredicates<'_> { +) -> &ty::GenericPredicates<'_> { debug!("super_predicates(trait_def_id={:?})", trait_def_id); let trait_hir_id = tcx.hir().as_local_hir_id(trait_def_id).unwrap(); @@ -732,23 +732,21 @@ fn super_predicates_of( generics, item.hir_id, self_param_ty, OnlySelfBounds(!is_trait_alias)); // Combine the two lists to form the complete set of superbounds: - let superbounds = &*tcx.arena.alloc_from_iter( - superbounds1.into_iter().chain(superbounds2) - ); + let superbounds: Vec<_> = superbounds1.into_iter().chain(superbounds2).collect(); // Now require that immediate supertraits are converted, // which will, in turn, reach indirect supertraits. - for &(pred, span) in superbounds { + for &(pred, span) in &superbounds { debug!("superbound: {:?}", pred); if let ty::Predicate::Trait(bound) = pred { tcx.at(span).super_predicates_of(bound.def_id()); } } - ty::GenericPredicates { + tcx.arena.alloc(ty::GenericPredicates { parent: None, predicates: superbounds, - } + }) } fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TraitDef { @@ -961,7 +959,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { opt_self = Some(ty::GenericParamDef { index: 0, - name: kw::SelfUpper, + name: kw::SelfUpper.as_interned_str(), def_id: tcx.hir().local_def_id(param_id), pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { @@ -1006,7 +1004,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { early_lifetimes .enumerate() .map(|(i, param)| ty::GenericParamDef { - name: param.name.ident().name, + name: param.name.ident().as_interned_str(), index: own_start + i as u32, def_id: tcx.hir().local_def_id(param.hir_id), pure_wrt_drop: param.pure_wrt_drop, @@ -1060,7 +1058,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { let param_def = ty::GenericParamDef { index: type_start + i as u32, - name: param.name.ident().name, + name: param.name.ident().as_interned_str(), def_id: tcx.hir().local_def_id(param.hir_id), pure_wrt_drop: param.pure_wrt_drop, kind, @@ -1090,7 +1088,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { .enumerate() .map(|(i, &arg)| ty::GenericParamDef { index: type_start + i as u32, - name: Symbol::intern(arg), + name: InternedString::intern(arg), def_id, pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { @@ -1105,7 +1103,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { params.extend(upvars.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| { ty::GenericParamDef { index: type_start + i, - name: Symbol::intern(""), + name: InternedString::intern(""), def_id, pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { @@ -1364,7 +1362,10 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option, def_id: DefId, fail: bool) -> Option match ¶m.kind { - hir::GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty), - hir::GenericParamKind::Const { ty: ref hir_ty, .. } => { - let ty = icx.to_ty(hir_ty); - if !tcx.features().const_compare_raw_pointers { - let err = match ty.peel_refs().kind { - ty::FnPtr(_) => Some("function pointers"), - ty::RawPtr(_) => Some("raw pointers"), - _ => None, - }; - if let Some(unsupported_type) = err { - feature_gate::emit_feature_err( - &tcx.sess.parse_sess, - sym::const_compare_raw_pointers, - hir_ty.span, - feature_gate::GateIssue::Language, - &format!( - "using {} as const generic parameters is unstable", - unsupported_type - ), - ); - }; - } - if ty::search_for_structural_match_violation(tcx, ty).is_some() { - struct_span_err!( - tcx.sess, - hir_ty.span, - E0741, - "the types of const generic parameters must derive `PartialEq` and `Eq`", - ).span_label( - hir_ty.span, - format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty), - ).emit(); - } - ty + hir::GenericParamKind::Type { default: Some(ref ty), .. } | + hir::GenericParamKind::Const { ref ty, .. } => { + icx.to_ty(ty) } x => { if !fail { @@ -1888,7 +1858,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { // the signature of a closure, you should use the // `closure_sig` method on the `ClosureSubsts`: // - // closure_substs.sig(def_id, tcx) + // closure_substs.closure_sig(def_id, tcx) // // or, inside of an inference context, you can use // @@ -1971,7 +1941,7 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>( fn predicates_defined_on( tcx: TyCtxt<'_>, def_id: DefId, -) -> ty::GenericPredicates<'_> { +) -> &ty::GenericPredicates<'_> { debug!("predicates_defined_on({:?})", def_id); let mut result = tcx.explicit_predicates_of(def_id); debug!( @@ -1987,13 +1957,9 @@ fn predicates_defined_on( def_id, inferred_outlives, ); - result.predicates = tcx.arena.alloc_from_iter( - result.predicates.iter().copied().chain( - // FIXME(eddyb) use better spans - maybe add `Span`s - // to `inferred_outlives_of` predicates as well? - inferred_outlives.iter().map(|&p| (p, span)), - ), - ); + let mut predicates = (*result).clone(); + predicates.predicates.extend(inferred_outlives.iter().map(|&p| (p, span))); + result = tcx.arena.alloc(predicates); } debug!("predicates_defined_on({:?}) = {:?}", def_id, result); result @@ -2002,7 +1968,7 @@ fn predicates_defined_on( /// Returns a list of all type predicates (explicit and implicit) for the definition with /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus /// `Self: Trait` predicates for traits. -fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { +fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::GenericPredicates<'_> { let mut result = tcx.predicates_defined_on(def_id); if tcx.is_trait(def_id) { @@ -2019,11 +1985,9 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { // used, and adding the predicate into this list ensures // that this is done. let span = tcx.def_span(def_id); - result.predicates = tcx.arena.alloc_from_iter( - result.predicates.iter().copied().chain( - std::iter::once((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)) - ), - ); + let mut predicates = (*result).clone(); + predicates.predicates.push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)); + result = tcx.arena.alloc(predicates); } debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); result @@ -2034,7 +1998,7 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { fn explicit_predicates_of( tcx: TyCtxt<'_>, def_id: DefId, -) -> ty::GenericPredicates<'_> { +) -> &ty::GenericPredicates<'_> { use rustc::hir::*; use rustc_data_structures::fx::FxHashSet; @@ -2043,7 +2007,6 @@ fn explicit_predicates_of( /// A data structure with unique elements, which preserves order of insertion. /// Preserving the order of insertion is important here so as not to break /// compile-fail UI tests. - // FIXME(eddyb) just use `IndexSet` from `indexmap`. struct UniquePredicates<'tcx> { predicates: Vec<(ty::Predicate<'tcx>, Span)>, uniques: FxHashSet<(ty::Predicate<'tcx>, Span)>, @@ -2153,10 +2116,10 @@ fn explicit_predicates_of( let bounds_predicates = bounds.predicates(tcx, opaque_ty); if impl_trait_fn.is_some() { // opaque types - return ty::GenericPredicates { + return tcx.arena.alloc(ty::GenericPredicates { parent: None, - predicates: tcx.arena.alloc_from_iter(bounds_predicates), - }; + predicates: bounds_predicates, + }); } else { // named opaque types predicates.extend(bounds_predicates); @@ -2209,7 +2172,7 @@ fn explicit_predicates_of( let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: tcx.hir().local_def_id(param.hir_id), index, - name: param.name.ident().name, + name: param.name.ident().as_interned_str(), })); index += 1; @@ -2232,7 +2195,7 @@ fn explicit_predicates_of( // type parameter (e.g., ``). for param in &ast_generics.params { if let GenericParamKind::Type { .. } = param.kind { - let name = param.name.ident().name; + let name = param.name.ident().as_interned_str(); let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); index += 1; @@ -2359,10 +2322,10 @@ fn explicit_predicates_of( ); } - let result = ty::GenericPredicates { + let result = tcx.arena.alloc(ty::GenericPredicates { parent: generics.parent, - predicates: tcx.arena.alloc_from_iter(predicates), - }; + predicates, + }); debug!("explicit_predicates_of(def_id={:?}) = {:?}", def_id, result); result } @@ -2600,7 +2563,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { let whitelist = tcx.target_features_whitelist(LOCAL_CRATE); let mut inline_span = None; - let mut link_ordinal_span = None; for attr in attrs.iter() { if attr.check_name(sym::cold) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD; @@ -2634,16 +2596,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED; } else if attr.check_name(sym::thread_local) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; - } else if attr.check_name(sym::track_caller) { - if tcx.fn_sig(id).abi() != abi::Abi::Rust { - struct_span_err!( - tcx.sess, - attr.span, - E0737, - "rust ABI is required to use `#[track_caller]`" - ).emit(); - } - codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; } else if attr.check_name(sym::export_name) { if let Some(s) = attr.value_str() { if s.as_str().contains("\0") { @@ -2692,11 +2644,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } } else if attr.check_name(sym::link_name) { codegen_fn_attrs.link_name = attr.value_str(); - } else if attr.check_name(sym::link_ordinal) { - link_ordinal_span = Some(attr.span); - if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) { - codegen_fn_attrs.link_ordinal = ordinal; - } } } @@ -2774,7 +2721,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { // purpose functions as they wouldn't have the right target features // enabled. For that reason we also forbid #[inline(always)] as it can't be // respected. - if codegen_fn_attrs.target_features.len() > 0 { if codegen_fn_attrs.inline == InlineAttr::Always { if let Some(span) = inline_span { @@ -2799,7 +2745,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.export_name = Some(name); codegen_fn_attrs.link_name = Some(name); } - check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span); // Internal symbols to the standard library all have no_mangle semantics in // that they have defined symbol names present in the function name. This @@ -2810,48 +2755,3 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs } - -fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { - use syntax::ast::{Lit, LitIntType, LitKind}; - let meta_item_list = attr.meta_item_list(); - let meta_item_list: Option<&[ast::NestedMetaItem]> = meta_item_list.as_ref().map(Vec::as_ref); - let sole_meta_list = match meta_item_list { - Some([item]) => item.literal(), - _ => None, - }; - if let Some(Lit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = sole_meta_list { - if *ordinal <= std::usize::MAX as u128 { - Some(*ordinal as usize) - } else { - let msg = format!( - "ordinal value in `link_ordinal` is too large: `{}`", - &ordinal - ); - tcx.sess.struct_span_err(attr.span, &msg) - .note("the value may not exceed `std::usize::MAX`") - .emit(); - None - } - } else { - tcx.sess.struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`") - .note("an unsuffixed integer value, e.g., `1`, is expected") - .emit(); - None - } -} - -fn check_link_name_xor_ordinal( - tcx: TyCtxt<'_>, - codegen_fn_attrs: &CodegenFnAttrs, - inline_span: Option, -) { - if codegen_fn_attrs.link_name.is_none() || codegen_fn_attrs.link_ordinal.is_none() { - return; - } - let msg = "cannot use `#[link_name]` with `#[link_ordinal]`"; - if let Some(span) = inline_span { - tcx.sess.span_err(span, msg); - } else { - tcx.sess.err(msg); - } -} diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs index 1fdf49fde55b5..31476eb731798 100644 --- a/src/librustc_typeck/constrained_generic_params.rs +++ b/src/librustc_typeck/constrained_generic_params.rs @@ -86,11 +86,11 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { pub fn identify_constrained_generic_params<'tcx>( tcx: TyCtxt<'tcx>, - predicates: ty::GenericPredicates<'tcx>, + predicates: &ty::GenericPredicates<'tcx>, impl_trait_ref: Option>, input_parameters: &mut FxHashSet, ) { - let mut predicates = predicates.predicates.to_vec(); + let mut predicates = predicates.predicates.clone(); setup_constraining_predicates(tcx, &mut predicates, impl_trait_ref, input_parameters); } diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 75b508a1bbf0f..e11dcfafb8f8b 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -194,7 +194,7 @@ a guard. ```compile_fail,E0029 let string = "salutations !"; -// The ordering relation for strings cannot be evaluated at compile time, +// The ordering relation for strings can't be evaluated at compile time, // so this doesn't work: match string { "hello" ..= "world" => {} @@ -348,7 +348,7 @@ fn main() { "##, E0044: r##" -You cannot use type or const parameters on foreign items. +You can't use type or const parameters on foreign items. Example of erroneous code: ```compile_fail,E0044 @@ -788,7 +788,7 @@ fn some_other_func() {} fn some_function() { SOME_CONST = 14; // error : a constant value cannot be changed! 1 = 3; // error : 1 isn't a valid place! - some_other_func() = 4; // error : we cannot assign value to a function! + some_other_func() = 4; // error : we can't assign value to a function! SomeStruct.x = 12; // error : SomeStruct a structure name but it is used // like a variable! } @@ -1873,14 +1873,13 @@ This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this differs from the behavior for `&T`, which is always `Copy`). "##, +/* E0205: r##" -#### Note: this error code is no longer emitted by the compiler. - An attempt to implement the `Copy` trait for an enum failed because one of the variants does not implement `Copy`. To fix this, you must implement `Copy` for the mentioned variant. Note that this may not be possible, as in the example of -```compile_fail,E0204 +```compile_fail,E0205 enum Foo { Bar(Vec), Baz, @@ -1893,7 +1892,7 @@ This fails because `Vec` does not implement `Copy` for any `T`. Here's another example that will fail: -```compile_fail,E0204 +```compile_fail,E0205 #[derive(Copy)] enum Foo<'a> { Bar(&'a mut bool), @@ -1904,6 +1903,7 @@ enum Foo<'a> { This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this differs from the behavior for `&T`, which is always `Copy`). "##, +*/ E0206: r##" You can only implement `Copy` for a struct or enum. Both of the following @@ -2126,9 +2126,8 @@ For information on the design of the orphan rules, see [RFC 1023]. [RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md "##, +/* E0211: r##" -#### Note: this error code is no longer emitted by the compiler. - You used a function or type which doesn't fit the requirements for where it was used. Erroneous code examples: @@ -2175,7 +2174,7 @@ extern "rust-intrinsic" { } ``` -The second case example is a bit particular: the main function must always +The second case example is a bit particular : the main function must always have this definition: ```compile_fail @@ -2207,6 +2206,7 @@ impl Foo { } ``` "##, + */ E0220: r##" You used an associated type which isn't defined in the trait. @@ -2727,9 +2727,14 @@ impl CoerceUnsized> for MyType [`CoerceUnsized`]: https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html "##, -E0329: r##" -#### Note: this error code is no longer emitted by the compiler. +/* +// Associated consts can now be accessed through generic type parameters, and +// this error is no longer emitted. +// +// FIXME: consider whether to leave it in the error index, or remove it entirely +// as associated consts is not stabilized yet. +E0329: r##" An attempt was made to access an associated constant through either a generic type parameter or `Self`. This is not supported yet. An example causing this error is shown below: @@ -2760,15 +2765,12 @@ trait Foo { struct MyStruct; -impl Foo for MyStruct { - const BAR: f64 = 0f64; -} - fn get_bar_good() -> f64 { ::BAR } ``` "##, +*/ E0366: r##" An attempt was made to implement `Drop` on a concrete specialization of a @@ -3608,43 +3610,6 @@ match r { ``` "##, -E0533: r##" -An item which isn't a unit struct, a variant, nor a constant has been used as a -match pattern. - -Erroneous code example: - -```compile_fail,E0533 -struct Tortoise; - -impl Tortoise { - fn turtle(&self) -> u32 { 0 } -} - -match 0u32 { - Tortoise::turtle => {} // Error! - _ => {} -} -if let Tortoise::turtle = 0u32 {} // Same error! -``` - -If you want to match against a value returned by a method, you need to bind the -value first: - -``` -struct Tortoise; - -impl Tortoise { - fn turtle(&self) -> u32 { 0 } -} - -match 0u32 { - x if x == Tortoise.turtle() => {} // Bound into `x` then we compare it! - _ => {} -} -``` -"##, - E0534: r##" The `inline` attribute was malformed. @@ -3891,33 +3856,6 @@ details. [issue #33685]: https://github.com/rust-lang/rust/issues/33685 "##, -E0588: r##" -A type with `packed` representation hint has a field with `align` -representation hint. - -Erroneous code example: - -```compile_fail,E0588 -#[repr(align(16))] -struct Aligned(i32); - -#[repr(packed)] // error! -struct Packed(Aligned); -``` - -Just like you cannot have both `align` and `packed` representation hints on a -same type, a `packed` type cannot contain another type with the `align` -representation hint. However, you can do the opposite: - -``` -#[repr(packed)] -struct Packed(i32); - -#[repr(align(16))] // ok! -struct Aligned(Packed); -``` -"##, - E0592: r##" This error occurs when you defined methods or associated functions with same name. @@ -4326,7 +4264,7 @@ extern { unsafe { printf(::std::ptr::null(), 0f32); - // error: cannot pass an `f32` to variadic function, cast to `c_double` + // error: can't pass an `f32` to variadic function, cast to `c_double` } ``` @@ -4890,10 +4828,6 @@ assert_eq!(1, discriminant(&Enum::Struct{a: 7, b: 11})); ``` "##, -E0740: r##" -A `union` cannot have fields with destructors. -"##, - E0733: r##" Recursion in an `async fn` requires boxing. For example, this will not compile: @@ -4936,99 +4870,6 @@ 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. "##, - -E0737: r##" -#[track_caller] requires functions to have the "Rust" ABI for implicitly -receiving caller location. See [RFC 2091] for details on this and other -restrictions. - -Erroneous code example: - -```compile_fail,E0737 -#![feature(track_caller)] - -#[track_caller] -extern "C" fn foo() {} -``` - -[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md -"##, - -E0738: r##" -#[track_caller] cannot be used in traits yet. This is due to limitations in the -compiler which are likely to be temporary. See [RFC 2091] for details on this -and other restrictions. - -Erroneous example with a trait method implementation: - -```compile_fail,E0738 -#![feature(track_caller)] - -trait Foo { - fn bar(&self); -} - -impl Foo for u64 { - #[track_caller] - fn bar(&self) {} -} -``` - -Erroneous example with a blanket trait method implementation: - -```compile_fail,E0738 -#![feature(track_caller)] - -trait Foo { - #[track_caller] - fn bar(&self) {} - fn baz(&self); -} -``` - -Erroneous example with a trait method declaration: - -```compile_fail,E0738 -#![feature(track_caller)] - -trait Foo { - fn bar(&self) {} - - #[track_caller] - fn baz(&self); -} -``` - -Note that while the compiler may be able to support the attribute in traits in -the future, [RFC 2091] prohibits their implementation without a follow-up RFC. - -[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md -"##, - -E0741: r##" -Only `structural_match` types (that is, types that derive `PartialEq` and `Eq`) -may be used as the types of const generic parameters. - -```compile_fail,E0741 -#![feature(const_generics)] - -struct A; - -struct B; // error! -``` - -To fix this example, we derive `PartialEq` and `Eq`. - -``` -#![feature(const_generics)] - -#[derive(PartialEq, Eq)] -struct A; - -struct B; // ok! -``` -"##, - ; // E0035, merged into E0087/E0089 // E0036, merged into E0087/E0089 @@ -5051,7 +4892,7 @@ struct B; // ok! // E0174, // E0182, // merged into E0229 E0183, -// E0187, // cannot infer the kind of the closure +// E0187, // can't infer the kind of the closure // 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 @@ -5094,20 +4935,22 @@ struct B; // ok! 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 -// E0564, // only named lifetimes are allowed in `impl Trait`, + E0564, // only named lifetimes are allowed in `impl Trait`, // but `{}` was found in the type `{}` E0587, // type has conflicting packed and align representation hints + E0588, // packed type cannot transitively contain a `[repr(align)]` type // E0611, // merged into E0616 // E0612, // merged into E0609 // E0613, // Removed (merged with E0609) E0627, // yield statement outside of generator literal - E0632, // cannot provide explicit generic arguments 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 -// E0645, // trait aliases not finished + E0645, // trait aliases not finished E0719, // duplicate values for associated type binding E0722, // Malformed `#[optimize]` attribute E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 2d188007712ad..ab660caa222ae 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -114,7 +114,7 @@ fn enforce_impl_params_are_constrained( let mut input_parameters = cgp::parameters_for_impl(impl_self_ty, impl_trait_ref); cgp::identify_constrained_generic_params( - tcx, impl_predicates, impl_trait_ref, &mut input_parameters); + tcx, &impl_predicates, impl_trait_ref, &mut input_parameters); // Disallow unconstrained lifetimes, but only if they appear in assoc types. let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs.iter() diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9374113e1c950..00be1c84599a3 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -67,6 +67,8 @@ This API is completely unstable and subject to change. #![feature(nll)] #![feature(slice_patterns)] #![feature(never_type)] +#![feature(inner_deref)] +#![feature(mem_take)] #![recursion_limit="256"] @@ -293,7 +295,7 @@ pub fn provide(providers: &mut Providers<'_>) { } pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { - let _prof_timer = tcx.prof.generic_activity("type_check_crate"); + tcx.sess.profiler(|p| p.start_activity("type-check crate")); // this ensures that later parts of type checking can assume that items // have valid types and not error @@ -345,6 +347,8 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { check_unused::check_crate(tcx); check_for_entry_fn(tcx); + tcx.sess.profiler(|p| p.end_activity("type-check crate")); + if tcx.sess.err_count() == 0 { Ok(()) } else { diff --git a/src/librustc_typeck/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs index 83194144216ee..40a57788c0710 100644 --- a/src/librustc_typeck/outlives/explicit.rs +++ b/src/librustc_typeck/outlives/explicit.rs @@ -30,7 +30,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { let mut required_predicates = RequiredPredicates::default(); // process predicates and convert to `RequiredPredicates` entry, see below - for (pred, _) in predicates.predicates { + for (pred, _) in predicates.predicates.iter() { match pred { ty::Predicate::TypeOutlives(predicate) => { let OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder(); diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs index d34605dc482a3..d83c97b522c67 100644 --- a/src/librustc_typeck/outlives/utils.rs +++ b/src/librustc_typeck/outlives/utils.rs @@ -161,14 +161,9 @@ fn is_free_region(tcx: TyCtxt<'_>, region: Region<'_>) -> bool { // ignore it. We can't put it on the struct header anyway. RegionKind::ReLateBound(..) => false, - // This can appear in `where Self: ` bounds (#64855): - // - // struct Bar(::Type) where Self: ; - // struct Baz<'a>(&'a Self) where Self: ; - RegionKind::ReEmpty => false, - // These regions don't appear in types from type declarations: - RegionKind::ReErased + RegionKind::ReEmpty + | RegionKind::ReErased | RegionKind::ReClosureBound(..) | RegionKind::ReScope(..) | RegionKind::ReVar(..) diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index e3de7fe20493e..0eb8b73016d10 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -11,5 +11,5 @@ path = "lib.rs" [dependencies] pulldown-cmark = { version = "0.5.3", default-features = false } minifier = "0.0.33" -rayon = { version = "0.3.0", package = "rustc-rayon" } +rayon = { version = "0.2.0", package = "rustc-rayon" } tempfile = "3" diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index b7f5ed9d004d4..18a84cd0eeb76 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -104,7 +104,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // regardless of the choice of `T`. let params = ( self.cx.tcx.generics_of(param_env_def_id), - ty::GenericPredicates::default(), + &&self.cx.tcx.common.empty_predicates, ).clean(self.cx).params; Generics { @@ -489,7 +489,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let mut generic_params = ( tcx.generics_of(param_env_def_id), - tcx.explicit_predicates_of(param_env_def_id), + &tcx.explicit_predicates_of(param_env_def_id), ).clean(self.cx).params; let mut has_sized = FxHashSet::default(); diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index ff59dcab672f3..afed11e7fab26 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -107,7 +107,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { unsafety: hir::Unsafety::Normal, generics: ( self.cx.tcx.generics_of(impl_def_id), - self.cx.tcx.explicit_predicates_of(impl_def_id), + &self.cx.tcx.explicit_predicates_of(impl_def_id), ).clean(self.cx), provided_trait_methods, // FIXME(eddyb) compute both `trait_` and `for_` from diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index d5ce9456f7f66..da3b52afadffb 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -9,7 +9,7 @@ use std::ops; use syntax::symbol::{Symbol, sym}; use syntax::ast::{MetaItem, MetaItemKind, NestedMetaItem, LitKind}; -use syntax::sess::ParseSess; +use syntax::parse::ParseSess; use syntax::feature_gate::Features; use syntax_pos::Span; @@ -360,7 +360,7 @@ impl<'a> fmt::Display for Html<'a> { ("target_arch", Some(arch)) => match &*arch.as_str() { "aarch64" => "AArch64", "arm" => "ARM", - "asmjs" => "JavaScript", + "asmjs" => "asm.js", "mips" => "MIPS", "mips64" => "MIPS-64", "msp430" => "MSP430", diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index a6a8fec429e20..532c5f67bf3ba 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -3,7 +3,7 @@ use std::iter::once; use syntax::ast; -use syntax_expand::base::MacroKind; +use syntax::ext::base::MacroKind; use syntax::symbol::sym; use syntax_pos::Span; @@ -193,7 +193,7 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait { let auto_trait = cx.tcx.trait_def(did).has_auto_impl; let trait_items = cx.tcx.associated_items(did).map(|item| item.clean(cx)).collect(); let predicates = cx.tcx.predicates_of(did); - let generics = (cx.tcx.generics_of(did), predicates).clean(cx); + let generics = (cx.tcx.generics_of(did), &predicates).clean(cx); let generics = filter_non_trait_generics(did, generics); let (generics, supertrait_bounds) = separate_supertrait_bounds(generics); let is_spotlight = load_attrs(cx, did).clean(cx).has_doc_flag(sym::spotlight); @@ -220,7 +220,7 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { let asyncness = cx.tcx.asyncness(did); let predicates = cx.tcx.predicates_of(did); let (generics, decl) = clean::enter_impl_trait(cx, || { - ((cx.tcx.generics_of(did), predicates).clean(cx), (did, sig).clean(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 { @@ -241,7 +241,7 @@ fn build_enum(cx: &DocContext<'_>, did: DefId) -> clean::Enum { let predicates = cx.tcx.explicit_predicates_of(did); clean::Enum { - generics: (cx.tcx.generics_of(did), predicates).clean(cx), + generics: (cx.tcx.generics_of(did), &predicates).clean(cx), variants_stripped: false, variants: cx.tcx.adt_def(did).variants.clean(cx), } @@ -257,7 +257,7 @@ fn build_struct(cx: &DocContext<'_>, did: DefId) -> clean::Struct { CtorKind::Fn => doctree::Tuple, CtorKind::Const => doctree::Unit, }, - generics: (cx.tcx.generics_of(did), predicates).clean(cx), + generics: (cx.tcx.generics_of(did), &predicates).clean(cx), fields: variant.fields.clean(cx), fields_stripped: false, } @@ -269,7 +269,7 @@ fn build_union(cx: &DocContext<'_>, did: DefId) -> clean::Union { clean::Union { struct_type: doctree::Plain, - generics: (cx.tcx.generics_of(did), predicates).clean(cx), + generics: (cx.tcx.generics_of(did), &predicates).clean(cx), fields: variant.fields.clean(cx), fields_stripped: false, } @@ -280,7 +280,7 @@ fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef { clean::Typedef { type_: cx.tcx.type_of(did).clean(cx), - generics: (cx.tcx.generics_of(did), predicates).clean(cx), + generics: (cx.tcx.generics_of(did), &predicates).clean(cx), } } @@ -376,7 +376,7 @@ pub fn build_impl(cx: &DocContext<'_>, did: DefId, attrs: Option>, } }).collect::>(), clean::enter_impl_trait(cx, || { - (tcx.generics_of(did), predicates).clean(cx) + (tcx.generics_of(did), &predicates).clean(cx) }), ) }; @@ -479,8 +479,8 @@ fn build_static(cx: &DocContext<'_>, did: DefId, mutable: bool) -> clean::Static fn build_macro(cx: &DocContext<'_>, did: DefId, name: ast::Name) -> clean::ItemEnum { let imported_from = cx.tcx.original_crate_name(did.krate); - match cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())) { - LoadedMacro::MacroDef(def, _) => { + match cx.cstore.load_macro_untracked(did, cx.sess()) { + LoadedMacro::MacroDef(def) => { let matchers: hir::HirVec = if let ast::ItemKind::MacroDef(ref def) = def.kind { let tts: Vec<_> = def.stream().into_trees().collect(); tts.chunks(4).map(|arm| arm[0].span()).collect() diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a642491b28181..ce21447105815 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -9,7 +9,7 @@ mod simplify; mod auto_trait; mod blanket_impl; -use rustc_index::vec::{IndexVec, Idx}; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_target::spec::abi::Abi; use rustc_typeck::hir_ty_to_ty; use rustc::infer::region_constraints::{RegionConstraintData, Constraint}; @@ -26,12 +26,12 @@ use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::ty::fold::TypeFolder; use rustc::ty::layout::VariantIdx; use rustc::util::nodemap::{FxHashMap, FxHashSet}; -use syntax::ast::{self, Attribute, AttrStyle, AttrItem, Ident}; +use syntax::ast::{self, AttrStyle, Ident}; use syntax::attr; -use syntax_expand::base::MacroKind; -use syntax::parse::lexer::comments; +use syntax::ext::base::MacroKind; use syntax::source_map::DUMMY_SP; use syntax::symbol::{Symbol, kw, sym}; +use syntax::symbol::InternedString; use syntax_pos::{self, Pos, FileName}; use std::collections::hash_map::Entry; @@ -198,7 +198,7 @@ pub fn krate(mut cx: &mut DocContext<'_>) -> Crate { Item { source: Span::empty(), name: Some(kw.clone()), - attrs, + attrs: attrs, visibility: Public, stability: get_stability(cx, def_id), deprecation: get_deprecation(cx, def_id), @@ -859,31 +859,8 @@ impl Attributes { let mut cfg = Cfg::True; let mut doc_line = 0; - /// Converts `attr` to a normal `#[doc="foo"]` comment, if it is a - /// comment like `///` or `/** */`. (Returns `attr` unchanged for - /// non-sugared doc attributes.) - pub fn with_desugared_doc(attr: &Attribute, f: impl FnOnce(&Attribute) -> T) -> T { - if attr.is_sugared_doc { - let comment = attr.value_str().unwrap(); - let meta = attr::mk_name_value_item_str( - Ident::with_dummy_span(sym::doc), - Symbol::intern(&comments::strip_doc_comment_decoration(&comment.as_str())), - DUMMY_SP, - ); - f(&Attribute { - item: AttrItem { path: meta.path, tokens: meta.kind.tokens(meta.span) }, - id: attr.id, - style: attr.style, - is_sugared_doc: true, - span: attr.span, - }) - } else { - f(attr) - } - } - let other_attrs = attrs.iter().filter_map(|attr| { - with_desugared_doc(attr, |attr| { + attr.with_desugared_doc(|attr| { if attr.check_name(sym::doc) { if let Some(mi) = attr.meta() { if let Some(value) = mi.value_str() { @@ -1330,7 +1307,7 @@ impl Clean> for ty::RegionKind { } } -#[derive(Clone, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] pub enum WherePredicate { BoundPredicate { ty: Type, bounds: Vec }, RegionPredicate { lifetime: Lifetime, bounds: Vec }, @@ -1593,7 +1570,7 @@ impl Clean for hir::GenericParam { did: cx.tcx.hir().local_def_id(self.hir_id), bounds: self.bounds.clean(cx), default: default.clean(cx), - synthetic, + synthetic: synthetic, }) } hir::GenericParamKind::Const { ref ty } => { @@ -1612,7 +1589,7 @@ impl Clean for hir::GenericParam { } // maybe use a Generic enum and use Vec? -#[derive(Clone, Debug, Default)] +#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)] pub struct Generics { pub params: Vec, pub where_predicates: Vec, @@ -1687,7 +1664,8 @@ impl Clean for hir::Generics { } } -impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx>) { +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; @@ -1705,7 +1683,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx .filter_map(|param| match param.kind { ty::GenericParamDefKind::Lifetime => None, ty::GenericParamDefKind::Type { synthetic, .. } => { - if param.name == kw::SelfUpper { + if param.name.as_symbol() == kw::SelfUpper { assert_eq!(param.index, 0); return None; } @@ -2054,7 +2032,6 @@ impl Clean for doctree::Function<'_> { pub struct FnDecl { pub inputs: Arguments, pub output: FunctionRetTy, - pub c_variadic: bool, pub attrs: Attributes, } @@ -2133,7 +2110,6 @@ impl<'a, A: Copy> Clean for (&'a hir::FnDecl, A) FnDecl { inputs: (&self.0.inputs[..], self.1).clean(cx), output: self.0.output.clean(cx), - c_variadic: self.0.c_variadic, attrs: Attributes::default(), } } @@ -2151,7 +2127,6 @@ impl<'tcx> Clean for (DefId, ty::PolyFnSig<'tcx>) { FnDecl { output: Return(sig.skip_binder().output().clean(cx)), attrs: Attributes::default(), - c_variadic: sig.skip_binder().c_variadic, inputs: Arguments { values: sig.skip_binder().inputs().iter().map(|t| { Argument { @@ -2235,7 +2210,7 @@ impl Clean for doctree::Trait<'_> { let is_spotlight = attrs.has_doc_flag(sym::spotlight); Item { name: Some(self.name.clean(cx)), - attrs, + attrs: attrs, source: self.whence.clean(cx), def_id: cx.tcx.hir().local_def_id(self.id), visibility: self.vis.clean(cx), @@ -2391,7 +2366,7 @@ impl Clean for ty::AssocItem { } ty::AssocKind::Method => { let generics = (cx.tcx.generics_of(self.def_id), - cx.tcx.explicit_predicates_of(self.def_id)).clean(cx); + &cx.tcx.explicit_predicates_of(self.def_id)).clean(cx); let sig = cx.tcx.fn_sig(self.def_id); let mut decl = (self.def_id, sig).clean(cx); @@ -2470,7 +2445,7 @@ impl Clean for ty::AssocItem { // all of the generics from there and then look for bounds that are // applied to this associated type in question. let predicates = cx.tcx.explicit_predicates_of(did); - let generics = (cx.tcx.generics_of(did), predicates).clean(cx); + let generics = (cx.tcx.generics_of(did), &predicates).clean(cx); let mut bounds = generics.where_predicates.iter().filter_map(|pred| { let (name, self_type, trait_, bounds) = match *pred { WherePredicate::BoundPredicate { @@ -2570,6 +2545,7 @@ pub enum Type { Slice(Box), Array(Box, String), Never, + CVarArgs, RawPointer(Mutability, Box), BorrowedRef { lifetime: Option, @@ -2607,6 +2583,7 @@ pub enum PrimitiveType { Reference, Fn, Never, + CVarArgs, } #[derive(Clone, Copy, Debug)] @@ -2810,6 +2787,7 @@ impl PrimitiveType { Reference => "reference", Fn => "fn", Never => "never", + CVarArgs => "...", } } @@ -2866,7 +2844,7 @@ impl Clean for hir::Ty { } else { Some(l.clean(cx)) }; - BorrowedRef {lifetime, mutability: m.mutbl.clean(cx), + BorrowedRef {lifetime: lifetime, mutability: m.mutbl.clean(cx), type_: box m.ty.clean(cx)} } TyKind::Slice(ref ty) => Slice(box ty.clean(cx)), @@ -3054,6 +3032,7 @@ impl Clean for hir::Ty { TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)), TyKind::Infer | TyKind::Err => Infer, TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind), + TyKind::CVarArgs(_) => CVarArgs, } } } @@ -3124,9 +3103,9 @@ impl<'tcx> Clean for Ty<'tcx> { let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], InternalSubsts::empty()); ResolvedPath { - path, + path: path, param_names: None, - did, + did: did, is_generic: false, } } @@ -3724,6 +3703,13 @@ impl Clean for ast::Name { } } +impl Clean for InternedString { + #[inline] + fn clean(&self, _: &DocContext<'_>) -> String { + self.to_string() + } +} + #[derive(Clone, Debug)] pub struct Typedef { pub type_: Type, @@ -3863,7 +3849,7 @@ impl Clean for hir::Mutability { } } -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, PartialEq, Eq, Copy, Debug, Hash)] pub enum ImplPolarity { Positive, Negative, @@ -3994,6 +3980,7 @@ fn build_deref_target_impls(cx: &DocContext<'_>, Reference => None, Fn => None, Never => None, + CVarArgs => tcx.lang_items().va_list(), }; if let Some(did) = did { if !did.is_local() { @@ -4289,7 +4276,7 @@ fn resolve_type(cx: &DocContext<'_>, _ => false, }; let did = register_res(&*cx, path.res); - ResolvedPath { path, param_names: None, did, is_generic } + ResolvedPath { path: path, param_names: None, did: did, is_generic: is_generic } } pub fn register_res(cx: &DocContext<'_>, res: Res) -> DefId { @@ -4522,6 +4509,7 @@ struct RegionDeps<'tcx> { smaller: FxHashSet> } +#[derive(Eq, PartialEq, Hash, Debug)] enum SimpleBound { TraitBound(Vec, Vec, Vec, hir::TraitBoundModifier), Outlives(Lifetime), diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 0b8d4d6c302f1..19ea781430041 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -53,8 +53,6 @@ pub struct Options { pub codegen_options_strs: Vec, /// Debugging (`-Z`) options to pass to the compiler. pub debugging_options: DebuggingOptions, - /// Debugging (`-Z`) options strings to pass to the compiler. - pub debugging_options_strs: Vec, /// The target used to compile the crate against. pub target: TargetTriple, /// Edition used when reading the crate. Defaults to "2015". Also used by default when @@ -345,7 +343,11 @@ impl Options { let output = matches.opt_str("o") .map(|s| PathBuf::from(&s)) .unwrap_or_else(|| PathBuf::from("doc")); - let cfgs = matches.opt_strs("cfg"); + let mut cfgs = matches.opt_strs("cfg"); + cfgs.push("rustdoc".to_string()); + if should_test { + cfgs.push("doctest".to_string()); + } let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s)); @@ -480,7 +482,6 @@ impl Options { 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 debugging_options_strs = matches.opt_strs("Z"); let lib_strs = matches.opt_strs("L"); let extern_strs = matches.opt_strs("extern"); let runtool = matches.opt_str("runtool"); @@ -502,7 +503,6 @@ impl Options { codegen_options, codegen_options_strs, debugging_options, - debugging_options_strs, target, edition, maybe_sysroot, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index b227f432a4e98..010e4cf6cd0d5 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -5,13 +5,14 @@ use rustc::hir::HirId; use rustc::middle::cstore::CrateStore; use rustc::middle::privacy::AccessLevels; use rustc::ty::{Ty, TyCtxt}; -use rustc::lint; +use rustc::lint::{self, LintPass}; use rustc::session::config::ErrorOutputType; use rustc::session::DiagnosticOutput; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_interface::interface; use rustc_driver::abort_on_err; use rustc_resolve as resolve; +use rustc_metadata::cstore::CStore; use syntax::source_map; use syntax::attr; @@ -42,6 +43,7 @@ pub struct DocContext<'tcx> { pub tcx: TyCtxt<'tcx>, pub resolver: Rc>, + pub cstore: Lrc, /// Later on moved into `html::render::CACHE_KEY` pub renderinfo: RefCell, /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY` @@ -115,7 +117,9 @@ impl<'tcx> DocContext<'tcx> { .def_path_table() .next_id() } else { - self.enter_resolver(|r| r.cstore().def_path_table(crate_num).next_id()) + self.cstore + .def_path_table(crate_num) + .next_id() }; DefId { @@ -230,7 +234,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt error_format, libs, externs, - mut cfgs, + cfgs, codegen_options, debugging_options, target, @@ -246,9 +250,6 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt .. } = options; - // Add the rustdoc cfg into the doc build. - cfgs.push("rustdoc".to_string()); - let cpath = Some(input.clone()); let input = Input::File(input); @@ -269,9 +270,10 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned()); let lints = || { - lint::builtin::HardwiredLints::get_lints() + lint::builtin::HardwiredLints + .get_lints() .into_iter() - .chain(rustc_lint::SoftLints::get_lints().into_iter()) + .chain(rustc_lint::SoftLints.get_lints().into_iter()) }; let lint_opts = lints().filter_map(|lint| { @@ -324,7 +326,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let config = interface::Config { opts: sessopts, - crate_cfg: interface::parse_cfgspecs(cfgs), + crate_cfg: config::parse_cfgspecs(cfgs), input, input_path: cpath, output_file: None, @@ -334,7 +336,6 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt stderr: None, crate_name, lint_caps, - register_lints: None, }; interface::run_compiler_in_existing_thread_pool(config, |compiler| { @@ -372,6 +373,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut ctxt = DocContext { tcx, resolver, + cstore: compiler.cstore().clone(), external_traits: Default::default(), active_extern_traits: Default::default(), renderinfo: RefCell::new(renderinfo), diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index bbc00147ee14e..6e453561f6da2 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -4,7 +4,7 @@ pub use self::StructType::*; use syntax::ast; use syntax::ast::Name; -use syntax_expand::base::MacroKind; +use syntax::ext::base::MacroKind; use syntax_pos::{self, Span}; use rustc::hir; @@ -59,7 +59,7 @@ impl Module<'hir> { fns : Vec::new(), mods : Vec::new(), typedefs : Vec::new(), - opaque_tys : Vec::new(), + opaque_tys : Vec::new(), statics : Vec::new(), constants : Vec::new(), traits : Vec::new(), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 4cde868201eef..fafd43cb60b69 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -657,6 +657,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> primitive_link(f, PrimitiveType::Array, &format!("; {}]", n)) } 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", @@ -902,15 +903,12 @@ impl clean::BareFunctionDecl { impl clean::FnDecl { crate fn print(&self) -> impl fmt::Display + '_ { display_fn(move |f| { - let ellipsis = if self.c_variadic { ", ..." } else { "" }; if f.alternate() { write!(f, - "({args:#}{ellipsis}){arrow:#}", - args = self.inputs.print(), ellipsis = ellipsis, arrow = self.output.print()) + "({args:#}){arrow:#}", args = self.inputs.print(), arrow = self.output.print()) } else { write!(f, - "({args}{ellipsis}){arrow}", - args = self.inputs.print(), ellipsis = ellipsis, arrow = self.output.print()) + "({args}){arrow}", args = self.inputs.print(), arrow = self.output.print()) } }) } @@ -977,12 +975,7 @@ impl Function<'_> { } } - let mut args_plain = format!("({})", args_plain); - - if decl.c_variadic { - args.push_str(",
..."); - args_plain.push_str(", ..."); - } + let args_plain = format!("({})", args_plain); let output = if let hir::IsAsync::Async = asyncness { Cow::Owned(decl.sugared_async_return_type()) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 30c9453a643d4..5d86ee9721b75 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -14,7 +14,7 @@ use std::io::prelude::*; use syntax::source_map::{SourceMap, FilePathMapping}; use syntax::parse::lexer; use syntax::parse::token::{self, Token}; -use syntax::sess::ParseSess; +use syntax::parse; use syntax::symbol::{kw, sym}; use syntax_pos::{Span, FileName}; @@ -33,7 +33,7 @@ pub fn render_with_highlighting( class, tooltip).unwrap(); } - let sess = ParseSess::new(FilePathMapping::empty()); + let sess = parse::ParseSess::new(FilePathMapping::empty()); let fm = sess.source_map().new_source_file( FileName::Custom(String::from("rustdoc-highlighting")), src.to_owned(), diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index e015739b03c40..5fb9afd6c49a0 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -1,7 +1,7 @@ //! Item types. use std::fmt; -use syntax_expand::base::MacroKind; +use syntax::ext::base::MacroKind; use crate::clean; /// Item type. Corresponds to `clean::ItemEnum` variants. diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 414c3137376a9..301dddbbfb9b2 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -45,11 +45,10 @@ use errors; use serialize::json::{ToJson, Json, as_json}; use syntax::ast; use syntax::edition::Edition; -use syntax::feature_gate::UnstableFeatures; -use syntax::print::pprust; +use syntax::ext::base::MacroKind; use syntax::source_map::FileName; +use syntax::feature_gate::UnstableFeatures; use syntax::symbol::{Symbol, sym}; -use syntax_expand::base::MacroKind; use rustc::hir::def_id::DefId; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; @@ -575,7 +574,7 @@ fn write_shared( let write = |p, c| { cx.shared.fs.write(p, c) }; if (*cx.shared).layout.logo.is_empty() { - write(cx.path("rust-logo.png"), static_files::RUST_LOGO)?; + write(cx.path("rust-log.png"), static_files::RUST_LOGO)?; } if (*cx.shared).layout.favicon.is_empty() { write(cx.path("favicon.ico"), static_files::RUST_FAVICON)?; @@ -1241,7 +1240,6 @@ fn settings(root_path: &str, suffix: &str) -> String { ("go-to-only-result", "Directly go to item in search if there is only one result", false), ("line-numbers", "Show line numbers on code examples", false), - ("disable-shortcuts", "Disable keyboard shortcuts", false), ]; format!( "

\ @@ -2959,7 +2957,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) { } fn render_attribute(attr: &ast::MetaItem) -> Option { - let path = pprust::path_to_string(&attr.path); + let path = attr.path.to_string(); if attr.is_word() { Some(path) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index a0e07d58c9da9..17a940cc4c9f8 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -79,7 +79,6 @@ function getSearchElement() { "derive", "traitalias"]; - var disableShortcuts = getCurrentValue("rustdoc-disable-shortcuts") === "true"; var search_input = getSearchInput(); // On the search screen, so you remain on the last tab you opened. @@ -295,7 +294,7 @@ function getSearchElement() { function handleShortcut(ev) { // Don't interfere with browser shortcuts - if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts === true) { + if (ev.ctrlKey || ev.altKey || ev.metaKey) { return; } diff --git a/src/librustdoc/html/static/noscript.css b/src/librustdoc/html/static/noscript.css index 832bd9ba2d628..4a434d49e4dfe 100644 --- a/src/librustdoc/html/static/noscript.css +++ b/src/librustdoc/html/static/noscript.css @@ -5,11 +5,3 @@ .loading-content { display: none; } - -#main > h2 + div, #main > h3 + div { - display: block; -} - -#main > h2 + h3 { - display: flex; -} diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 64c858238dbce..244b24af43f35 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -183,7 +183,7 @@ nav.sub { position: fixed; left: 0; top: 0; - bottom: 0; + height: 100vh; overflow: auto; } @@ -573,7 +573,7 @@ h4 > code, h3 > code, .invisible > code { margin-top: 0; } -nav:not(.sidebar) { +nav { border-bottom: 1px solid; padding-bottom: 10px; margin-bottom: 10px; diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index c3116dbe7a242..e44ae2ad10cee 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -129,7 +129,7 @@ pre { pre.rust .comment { color: #8d8d8b; } pre.rust .doccomment { color: #8ca375; } -nav:not(.sidebar) { +nav { border-bottom-color: #4e4e4e; } nav.main .current { diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index e2bf9f9d2f23a..4c37000dde2c5 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -129,7 +129,7 @@ pre { pre.rust .comment { color: #8E908C; } pre.rust .doccomment { color: #4D4D4C; } -nav:not(.sidebar) { +nav { border-bottom-color: #e0e0e0; } nav.main .current { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8cd32a3d1b508..2985e7f70b52f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -14,7 +14,9 @@ #![feature(crate_visibility_modifier)] #![feature(const_fn)] #![feature(drain_filter)] +#![feature(inner_deref)] #![feature(never_type)] +#![feature(mem_take)] #![feature(unicode_internals)] #![recursion_limit="256"] @@ -23,7 +25,6 @@ extern crate getopts; extern crate env_logger; extern crate rustc; extern crate rustc_data_structures; -extern crate rustc_index; extern crate rustc_driver; extern crate rustc_resolve; extern crate rustc_lint; @@ -34,7 +35,6 @@ extern crate rustc_typeck; extern crate rustc_lexer; extern crate serialize; extern crate syntax; -extern crate syntax_expand; extern crate syntax_pos; extern crate test as testing; #[macro_use] extern crate log; @@ -486,8 +486,8 @@ where R: 'static + Send, krate.version = crate_version; f(Output { - krate, - renderinfo, + krate: krate, + renderinfo: renderinfo, renderopts, }) }); diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 10e15ab8881af..32044e48b6f99 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -1,7 +1,6 @@ use errors::Applicability; use syntax::parse::lexer::{StringReader as Lexer}; -use syntax::parse::token; -use syntax::sess::ParseSess; +use syntax::parse::{ParseSess, token}; use syntax::source_map::FilePathMapping; use syntax_pos::{InnerSpan, FileName}; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index caa7f08f68cff..9186ed514202f 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -7,7 +7,7 @@ use rustc::ty; use rustc_resolve::ParentScope; use syntax; use syntax::ast::{self, Ident}; -use syntax_expand::base::SyntaxExtensionKind; +use syntax::ext::base::SyntaxExtensionKind; use syntax::feature_gate::UnstableFeatures; use syntax::symbol::Symbol; use syntax_pos::DUMMY_SP; @@ -432,13 +432,13 @@ 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, &ParentScope::module(resolver.graph_root()), 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"))); } } - if let Some(res) = resolver.all_macros().get(&Symbol::intern(path_str)) { + if let Some(res) = resolver.all_macros.get(&Symbol::intern(path_str)) { return Some(res.map_id(|_| panic!("unexpected id"))); } None diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 07dc1e4e9157a..6576165b6ce74 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -62,12 +62,9 @@ pub fn run(options: Options) -> i32 { ..config::Options::default() }; - let mut cfgs = options.cfgs.clone(); - cfgs.push("rustdoc".to_owned()); - cfgs.push("doctest".to_owned()); let config = interface::Config { opts: sessopts, - crate_cfg: interface::parse_cfgspecs(cfgs), + crate_cfg: config::parse_cfgspecs(options.cfgs.clone()), input, input_path: None, output_file: None, @@ -77,7 +74,6 @@ pub fn run(options: Options) -> i32 { stderr: None, crate_name: options.crate_name.clone(), lint_caps: Default::default(), - register_lints: None, }; let mut test_args = options.test_args.clone(); @@ -281,9 +277,6 @@ fn run_test( for codegen_options_str in &options.codegen_options_strs { compiler.arg("-C").arg(&codegen_options_str); } - for debugging_option_str in &options.debugging_options_strs { - compiler.arg("-Z").arg(&debugging_option_str); - } if no_run { compiler.arg("--emit=metadata"); } @@ -398,7 +391,7 @@ pub fn make_test(s: &str, // Uses libsyntax to parse the doctest and find if there's a main fn and the extern // crate already is included. let (already_has_main, already_has_extern_crate, found_macro) = with_globals(edition, || { - use crate::syntax::{parse, sess::ParseSess, source_map::FilePathMapping}; + use crate::syntax::{parse::{self, ParseSess}, source_map::FilePathMapping}; use errors::emitter::EmitterWriter; use errors::Handler; @@ -709,7 +702,6 @@ impl Tester for Collector { // compiler failures are test failures should_panic: testing::ShouldPanic::No, allow_fail: config.allow_fail, - test_type: testing::TestType::DocTest, }, testfn: testing::DynTestFn(box move || { let res = run_test( diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 70c30687dabca..b6a90e1fb988b 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -8,7 +8,7 @@ use rustc::middle::privacy::AccessLevel; use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::ty::TyCtxt; use syntax::ast; -use syntax_expand::base::MacroKind; +use syntax::ext::base::MacroKind; use syntax::source_map::Spanned; use syntax::symbol::sym; use syntax_pos::{self, Span}; diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index f2e9be14c8d12..d981740780e6f 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -143,7 +143,7 @@ impl Decodable for BTreeSet } impl Encodable for HashMap - where K: Encodable + Eq, + where K: Encodable + Hash + Eq, V: Encodable, S: BuildHasher, { @@ -180,7 +180,7 @@ impl Decodable for HashMap } impl Encodable for HashSet - where T: Encodable + Eq, + where T: Encodable + Hash + Eq, S: BuildHasher, { fn encode(&self, s: &mut E) -> Result<(), E::Error> { diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index d2e360f5e20fd..d0007074a823c 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -1053,12 +1053,12 @@ impl Json { /// a value associated with the provided key is found. If no value is found /// or the Json value is not an Object, returns `None`. pub fn search(&self, key: &str) -> Option<&Json> { - match *self { - Json::Object(ref map) => { + match self { + &Json::Object(ref map) => { match map.get(key) { Some(json_value) => Some(json_value), None => { - for v in map.values() { + for (_, v) in map { match v.search(key) { x if x.is_some() => return x, _ => () @@ -1487,12 +1487,12 @@ impl> Parser { } fn parse_number(&mut self) -> JsonEvent { - let neg = if self.ch_is('-') { + let mut neg = false; + + if self.ch_is('-') { self.bump(); - true - } else { - false - }; + neg = true; + } let res = match self.parse_u64() { Ok(res) => res, @@ -2162,9 +2162,10 @@ impl crate::Decoder for Decoder { let s = self.read_str()?; { let mut it = s.chars(); - if let (Some(c), None) = (it.next(), it.next()) { + match (it.next(), it.next()) { // exactly one character - return Ok(c); + (Some(c), None) => return Ok(c), + _ => () } } Err(ExpectedError("single character string".to_owned(), s.to_string())) diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index efe5c9d28f0d2..ee4b367b5c5b9 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -23,7 +23,7 @@ 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.6.2", default-features = false, features = ['rustc-dep-of-std'] } +hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] } [dependencies.backtrace_rs] package = "backtrace" diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index 9f400713a86d4..61c42a56071e6 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -113,7 +113,7 @@ pub struct Backtrace { /// The current status of a backtrace, indicating whether it was captured or /// whether it is empty for some other reason. #[non_exhaustive] -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug)] pub enum BacktraceStatus { /// Capturing a backtrace is not supported, likely because it's not /// implemented for the current platform. diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 6b0225a1b443a..69abbde9e6eba 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -192,9 +192,14 @@ use crate::sys; /// ``` /// use std::collections::HashMap; /// -/// let timber_resources: HashMap<&str, i32> = [("Norway", 100), ("Denmark", 50), ("Iceland", 10)] -/// .iter().cloned().collect(); -/// // use the values stored in map +/// 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)] @@ -2030,31 +2035,6 @@ impl<'a, K, V> Entry<'a, K, V> { Vacant(entry) => Vacant(entry), } } - - /// Sets the value of the entry, and returns an OccupiedEntry. - /// - /// # Examples - /// - /// ``` - /// #![feature(entry_insert)] - /// use std::collections::HashMap; - /// - /// let mut map: HashMap<&str, String> = HashMap::new(); - /// let entry = map.entry("poneyland").insert("hoho".to_string()); - /// - /// assert_eq!(entry.key(), &"poneyland"); - /// ``` - #[inline] - #[unstable(feature = "entry_insert", issue = "65225")] - pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V> { - match self { - Occupied(mut entry) => { - entry.insert(value); - entry - }, - Vacant(entry) => entry.insert_entry(value), - } - } } impl<'a, K, V: Default> Entry<'a, K, V> { @@ -2372,28 +2352,6 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { pub fn insert(self, value: V) -> &'a mut V { self.base.insert(value) } - - /// Sets the value of the entry with the VacantEntry's key, - /// and returns an OccupiedEntry. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashMap; - /// use std::collections::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] - fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { - let base = self.base.insert_entry(value); - OccupiedEntry { base } - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2409,8 +2367,6 @@ where } } -/// Inserts all new key-values from the iterator and replaces values with existing -/// keys with new values returned from the iterator. #[stable(feature = "rust1", since = "1.0.0")] impl Extend<(K, V)> for HashMap where diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 092fb44346848..26db651ef8911 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -93,9 +93,11 @@ use super::map::{self, HashMap, Keys, RandomState}; /// ``` /// use std::collections::HashSet; /// -/// let viking_names: HashSet<&'static str> = -/// [ "Einar", "Olaf", "Harald" ].iter().cloned().collect(); -/// // use the values stored in the set +/// fn main() { +/// let viking_names: HashSet<&'static str> = +/// [ "Einar", "Olaf", "Harald" ].iter().cloned().collect(); +/// // use the values stored in the set +/// } /// ``` /// /// [`Cell`]: ../../std/cell/struct.Cell.html diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 6b9a35fccc4dc..4a1bb75d588c9 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -269,8 +269,8 @@ impl<'a, E: Error + 'a> From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + Send + Sync + 'a> From for Box { - /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of - /// dyn [`Error`] + [`Send`] + [`Sync`]. + /// Converts a type of [`Error`] + [`trait@Send`] + [`trait@Sync`] into a box of + /// dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// @@ -313,7 +313,7 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box for Box { - /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// Converts a [`String`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// @@ -377,7 +377,7 @@ impl From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From<&str> for Box { - /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// Converts a [`str`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// @@ -420,7 +420,7 @@ impl From<&str> for Box { #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a, 'b> From> for Box { - /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// Converts a [`Cow`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. /// /// [`Cow`]: ../borrow/enum.Cow.html /// [`Error`]: ../error/trait.Error.html diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 6dcda98631014..d7f4cc5d1fdaa 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -327,31 +327,7 @@ impl CString { /// [`NulError`]: struct.NulError.html #[stable(feature = "rust1", since = "1.0.0")] pub fn new>>(t: T) -> Result { - trait SpecIntoVec { - fn into_vec(self) -> Vec; - } - impl>> SpecIntoVec for T { - default fn into_vec(self) -> Vec { - self.into() - } - } - // Specialization for avoiding reallocation. - impl SpecIntoVec for &'_ [u8] { - fn into_vec(self) -> Vec { - let mut v = Vec::with_capacity(self.len() + 1); - v.extend(self); - v - } - } - impl SpecIntoVec for &'_ str { - fn into_vec(self) -> Vec { - let mut v = Vec::with_capacity(self.len() + 1); - v.extend(self.as_bytes()); - v - } - } - - Self::_new(SpecIntoVec::into_vec(t)) + Self::_new(t.into()) } fn _new(bytes: Vec) -> Result { @@ -943,7 +919,7 @@ impl Error for IntoStringError { "C string contained non-utf8 bytes" } - fn source(&self) -> Option<&(dyn Error + 'static)> { + fn cause(&self) -> Option<&dyn Error> { Some(&self.error) } } diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 6595f54162f0a..8933f027a065f 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1090,14 +1090,13 @@ impl Metadata { /// Returns the creation time listed in this metadata. /// - /// The returned value corresponds to the `btime` field of `statx` on - /// Linux kernel starting from to 4.11, the `birthtime` field of `stat` on other - /// Unix platforms, and the `ftCreationTime` field on Windows platforms. + /// The returned value corresponds to the `birthtime` field of `stat` on + /// Unix platforms and the `ftCreationTime` field on Windows platforms. /// /// # Errors /// /// This field may not be available on all platforms, and will return an - /// `Err` on platforms or filesystems where it is not available. + /// `Err` on platforms where it is not available. /// /// # Examples /// @@ -1110,7 +1109,7 @@ impl Metadata { /// if let Ok(time) = metadata.created() { /// println!("{:?}", time); /// } else { - /// println!("Not supported on this platform or filesystem"); + /// println!("Not supported on this platform"); /// } /// Ok(()) /// } @@ -3113,10 +3112,8 @@ mod tests { #[cfg(windows)] let invalid_options = 87; // ERROR_INVALID_PARAMETER - #[cfg(all(unix, not(target_os = "vxworks")))] + #[cfg(unix)] let invalid_options = "Invalid argument"; - #[cfg(target_os = "vxworks")] - let invalid_options = "invalid argument"; // Test various combinations of creation modes and access modes. // @@ -3444,18 +3441,5 @@ mod tests { check!(a.created()); check!(b.created()); } - - if cfg!(target_os = "linux") { - // Not always available - match (a.created(), b.created()) { - (Ok(t1), Ok(t2)) => assert!(t1 <= t2), - (Err(e1), Err(e2)) if e1.kind() == ErrorKind::Other && - e2.kind() == ErrorKind::Other => {} - (a, b) => panic!( - "creation time must be always supported or not supported: {:?} {:?}", - a, b, - ), - } - } } } diff --git a/src/libstd/future.rs b/src/libstd/future.rs index c65f71fb1a4e2..0406549ff0791 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -26,7 +26,6 @@ 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/stdio.rs b/src/libstd/io/stdio.rs index 6574ef13db953..c798ee0e2209a 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -762,7 +762,7 @@ pub fn set_print(sink: Option>) -> Option 12 { -/// break; -/// } -/// last = x; -/// } -/// -/// assert_eq!(last, 12); -/// println!("{}", last); -/// ``` -/// -/// A break expression is normally associated with the innermost loop enclosing the -/// `break` but a label can be used to specify which enclosing loop is affected. -/// -///```rust -/// 'outer: for i in 1..=5 { -/// println!("outer iteration (i): {}", i); -/// -/// 'inner: for j in 1..=200 { -/// println!(" inner iteration (j): {}", j); -/// if j >= 3 { -/// // breaks from inner loop, let's outer loop continue. -/// break; -/// } -/// if i >= 2 { -/// // breaks from outer loop, and directly to "Bye". -/// break 'outer; -/// } -/// } -/// } -/// println!("Bye."); -///``` -/// -/// When associated with `loop`, a break expression may be used to return a value from that loop. -/// This is only valid with `loop` and not with any other type of loop. -/// If no value is specified, `break;` returns `()`. -/// Every `break` within a loop must return the same type. -/// -/// ```rust -/// let (mut a, mut b) = (1, 1); -/// let result = loop { -/// if b > 10 { -/// break b; -/// } -/// let c = a + b; -/// a = b; -/// b = c; -/// }; -/// // first number in Fibonacci sequence over 10: -/// assert_eq!(result, 13); -/// println!("{}", result); -/// ``` -/// -/// For more details consult the [Reference on "break expression"] and the [Reference on "break and -/// loop values"]. -/// -/// [Reference on "break expression"]: ../reference/expressions/loop-expr.html#break-expressions -/// [Reference on "break and loop values"]: -/// ../reference/expressions/loop-expr.html#break-and-loop-values +/// The documentation for this keyword is [not yet complete]. Pull requests welcome! /// +/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod break_keyword { } #[doc(keyword = "const")] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c7adad896a51a..5d9683f8deda9 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -220,7 +220,7 @@ #![cfg_attr(test, feature(print_internals, set_stdio, update_panic_count))] #![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"), - feature(slice_index_methods, coerce_unsized, + feature(slice_index_methods, decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))] #![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array, maybe_uninit_extra))] @@ -251,7 +251,6 @@ #![feature(container_error_extra)] #![feature(core_intrinsics)] #![feature(custom_test_frameworks)] -#![feature(decl_macro)] #![feature(doc_alias)] #![feature(doc_cfg)] #![feature(doc_keyword)] @@ -276,14 +275,13 @@ #![feature(link_args)] #![feature(linkage)] #![feature(log_syntax)] -#![feature(manually_drop_take)] -#![feature(matches_macro)] #![feature(maybe_uninit_ref)] #![feature(maybe_uninit_slice)] +#![feature(mem_take)] #![feature(needs_panic_runtime)] #![feature(never_type)] #![feature(nll)] -#![cfg_attr(bootstrap, feature(non_exhaustive))] +#![feature(non_exhaustive)] #![feature(on_unimplemented)] #![feature(optin_builtin_traits)] #![feature(panic_info_message)] @@ -300,7 +298,6 @@ #![feature(slice_concat_ext)] #![feature(slice_internals)] #![feature(slice_patterns)] -#![feature(specialization)] #![feature(staged_api)] #![feature(std_internals)] #![feature(stdsimd)] @@ -308,6 +305,7 @@ #![feature(str_internals)] #![feature(test)] #![feature(thread_local)] +#![feature(todo_macro)] #![feature(toowned_clone_into)] #![feature(trace_macros)] #![feature(try_reserve)] @@ -529,7 +527,6 @@ pub use core::{ writeln, // Unstable todo, - matches, }; // Re-export built-in macros defined through libcore. diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index f9255b82fc83e..ca86a175058b5 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -217,9 +217,11 @@ impl SocketAddr { /// ``` /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; /// - /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); - /// assert_eq!(socket.is_ipv4(), true); - /// assert_eq!(socket.is_ipv6(), false); + /// fn main() { + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), true); + /// assert_eq!(socket.is_ipv6(), false); + /// } /// ``` #[stable(feature = "sockaddr_checker", since = "1.16.0")] pub fn is_ipv4(&self) -> bool { @@ -242,9 +244,12 @@ impl SocketAddr { /// ``` /// use std::net::{IpAddr, Ipv6Addr, SocketAddr}; /// - /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080); - /// assert_eq!(socket.is_ipv4(), false); - /// assert_eq!(socket.is_ipv6(), true); + /// fn main() { + /// let socket = SocketAddr::new( + /// IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), false); + /// assert_eq!(socket.is_ipv6(), true); + /// } /// ``` #[stable(feature = "sockaddr_checker", since = "1.16.0")] pub fn is_ipv6(&self) -> bool { diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 70b68d1348550..6b504056e5f87 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -197,8 +197,11 @@ impl IpAddr { /// /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true); + /// fn main() { + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), + /// true); + /// } /// ``` pub fn is_global(&self) -> bool { match self { @@ -248,11 +251,11 @@ impl IpAddr { /// /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true); - /// assert_eq!( - /// IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(), - /// true - /// ); + /// fn main() { + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)) + /// .is_documentation(), true); + /// } /// ``` pub fn is_documentation(&self) -> bool { match self { @@ -272,8 +275,11 @@ impl IpAddr { /// ``` /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false); + /// fn main() { + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), + /// false); + /// } /// ``` #[stable(feature = "ipaddr_checker", since = "1.16.0")] pub fn is_ipv4(&self) -> bool { @@ -294,8 +300,11 @@ impl IpAddr { /// ``` /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true); + /// fn main() { + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), + /// true); + /// } /// ``` #[stable(feature = "ipaddr_checker", since = "1.16.0")] pub fn is_ipv6(&self) -> bool { @@ -517,46 +526,48 @@ impl Ipv4Addr { /// /// use std::net::Ipv4Addr; /// - /// // private addresses are not global - /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false); - /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false); - /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false); + /// fn main() { + /// // private addresses are not global + /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false); + /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false); + /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false); /// - /// // the 0.0.0.0/8 block is not global - /// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false); - /// // in particular, the unspecified address is not global - /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false); + /// // the 0.0.0.0/8 block is not global + /// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false); + /// // in particular, the unspecified address is not global + /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false); /// - /// // the loopback address is not global - /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false); + /// // the loopback address is not global + /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false); /// - /// // link local addresses are not global - /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false); + /// // link local addresses are not global + /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false); /// - /// // the broadcast address is not global - /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false); + /// // the broadcast address is not global + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false); /// - /// // the broadcast address is not global - /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false); - /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false); - /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false); + /// // the broadcast address is not global + /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false); + /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false); + /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false); /// - /// // shared addresses are not global - /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false); + /// // shared addresses are not global + /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false); /// - /// // addresses reserved for protocol assignment are not global - /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false); - /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false); + /// // addresses reserved for protocol assignment are not global + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false); /// - /// // addresses reserved for future use are not global - /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false); + /// // addresses reserved for future use are not global + /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false); /// - /// // addresses reserved for network devices benchmarking are not global - /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false); + /// // addresses reserved for network devices benchmarking are not global + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false); /// - /// // All the other addresses are global - /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true); - /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); + /// // All the other addresses are global + /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true); + /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); + /// } /// ``` pub fn is_global(&self) -> bool { // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two @@ -589,9 +600,11 @@ impl Ipv4Addr { /// #![feature(ip)] /// use std::net::Ipv4Addr; /// - /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true); - /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); - /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); + /// fn main() { + /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true); + /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); + /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); + /// } /// ``` pub fn is_shared(&self) -> bool { self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000) @@ -618,12 +631,14 @@ impl Ipv4Addr { /// #![feature(ip)] /// use std::net::Ipv4Addr; /// - /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_ietf_protocol_assignment(), true); - /// assert_eq!(Ipv4Addr::new(192, 0, 0, 8).is_ietf_protocol_assignment(), true); - /// assert_eq!(Ipv4Addr::new(192, 0, 0, 9).is_ietf_protocol_assignment(), true); - /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_ietf_protocol_assignment(), true); - /// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false); - /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false); + /// fn main() { + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 8).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 9).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false); + /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false); + /// } /// ``` pub fn is_ietf_protocol_assignment(&self) -> bool { self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0 @@ -643,10 +658,12 @@ impl Ipv4Addr { /// #![feature(ip)] /// use std::net::Ipv4Addr; /// - /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false); - /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true); - /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); - /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); + /// fn main() { + /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false); + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true); + /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); + /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); + /// } /// ``` pub fn is_benchmarking(&self) -> bool { self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 @@ -673,12 +690,15 @@ impl Ipv4Addr { /// #![feature(ip)] /// use std::net::Ipv4Addr; /// - /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true); - /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true); + /// fn main() { + /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true); + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true); /// - /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false); - /// // The broadcast address is not considered as reserved for future use by this implementation - /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); + /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false); + /// // The broadcast address is not considered as reserved for future use by this + /// // implementation + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); + /// } /// ``` pub fn is_reserved(&self) -> bool { self.octets()[0] & 240 == 240 && !self.is_broadcast() @@ -768,10 +788,8 @@ impl Ipv4Addr { /// ``` /// use std::net::{Ipv4Addr, Ipv6Addr}; /// - /// assert_eq!( - /// Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(), - /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767) - /// ); + /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(), + /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv6_compatible(&self) -> Ipv6Addr { @@ -1143,9 +1161,11 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false); - /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true); + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true); + /// } /// ``` pub fn is_global(&self) -> bool { match self.multicast_scope() { @@ -1169,8 +1189,11 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false); - /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), + /// false); + /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); + /// } /// ``` pub fn is_unique_local(&self) -> bool { (self.segments()[0] & 0xfe00) == 0xfc00 @@ -1200,19 +1223,21 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0); - /// assert!(ip.is_unicast_link_local_strict()); + /// fn main() { + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local_strict()); /// - /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff); - /// assert!(ip.is_unicast_link_local_strict()); + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff); + /// assert!(ip.is_unicast_link_local_strict()); /// - /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0); - /// assert!(!ip.is_unicast_link_local_strict()); - /// assert!(ip.is_unicast_link_local()); + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0); + /// assert!(!ip.is_unicast_link_local_strict()); + /// assert!(ip.is_unicast_link_local()); /// - /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0); - /// assert!(!ip.is_unicast_link_local_strict()); - /// assert!(ip.is_unicast_link_local()); + /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0); + /// assert!(!ip.is_unicast_link_local_strict()); + /// assert!(ip.is_unicast_link_local()); + /// } /// ``` /// /// # See also @@ -1259,19 +1284,21 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0); - /// assert!(ip.is_unicast_link_local()); + /// fn main() { + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local()); /// - /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff); - /// assert!(ip.is_unicast_link_local()); + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff); + /// assert!(ip.is_unicast_link_local()); /// - /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0); - /// assert!(ip.is_unicast_link_local()); - /// assert!(!ip.is_unicast_link_local_strict()); + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local()); + /// assert!(!ip.is_unicast_link_local_strict()); /// - /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0); - /// assert!(ip.is_unicast_link_local()); - /// assert!(!ip.is_unicast_link_local_strict()); + /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local()); + /// assert!(!ip.is_unicast_link_local_strict()); + /// } /// ``` /// /// # See also @@ -1309,11 +1336,11 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// assert_eq!( - /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(), - /// false - /// ); - /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true); + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(), + /// false); + /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true); + /// } /// ``` /// /// # Warning @@ -1342,8 +1369,11 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false); - /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), + /// false); + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); + /// } /// ``` pub fn is_documentation(&self) -> bool { (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) @@ -1377,8 +1407,11 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true); + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), + /// true); + /// } /// ``` pub fn is_unicast_global(&self) -> bool { !self.is_multicast() @@ -1398,11 +1431,11 @@ impl Ipv6Addr { /// /// use std::net::{Ipv6Addr, Ipv6MulticastScope}; /// - /// assert_eq!( - /// Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(), - /// Some(Ipv6MulticastScope::Global) - /// ); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(), + /// Some(Ipv6MulticastScope::Global)); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); + /// } /// ``` pub fn multicast_scope(&self) -> Option { if self.is_multicast() { diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index a9e4457f42374..a5e7cd992f227 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -185,6 +185,7 @@ impl UdpSocket { /// # Examples /// /// ```no_run + /// #![feature(udp_peer_addr)] /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket}; /// /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); @@ -198,13 +199,14 @@ impl UdpSocket { /// [`NotConnected`]: ../../std/io/enum.ErrorKind.html#variant.NotConnected /// /// ```no_run + /// #![feature(udp_peer_addr)] /// use std::net::UdpSocket; /// /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); /// assert_eq!(socket.peer_addr().unwrap_err().kind(), - /// std::io::ErrorKind::NotConnected); + /// ::std::io::ErrorKind::NotConnected); /// ``` - #[stable(feature = "udp_peer_addr", since = "1.40.0")] + #[unstable(feature = "udp_peer_addr", issue = "59127")] pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 577673b7e405b..1d4fd98dd754f 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -12,9 +12,7 @@ use crate::ops::{Deref, DerefMut}; use crate::panicking; use crate::ptr::{Unique, NonNull}; use crate::rc::Rc; -use crate::sync::{Arc, Mutex, RwLock}; -#[cfg(not(bootstrap))] -use crate::sync::atomic; +use crate::sync::{Arc, Mutex, RwLock, atomic}; use crate::task::{Context, Poll}; use crate::thread::Result; @@ -242,49 +240,49 @@ impl RefUnwindSafe for Mutex {} #[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")] impl RefUnwindSafe for RwLock {} -#[cfg(target_has_atomic_load_store = "ptr")] +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] impl RefUnwindSafe for atomic::AtomicIsize {} -#[cfg(target_has_atomic_load_store = "8")] +#[cfg(target_has_atomic = "8")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicI8 {} -#[cfg(target_has_atomic_load_store = "16")] +#[cfg(target_has_atomic = "16")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicI16 {} -#[cfg(target_has_atomic_load_store = "32")] +#[cfg(target_has_atomic = "32")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicI32 {} -#[cfg(target_has_atomic_load_store = "64")] +#[cfg(target_has_atomic = "64")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicI64 {} -#[cfg(target_has_atomic_load_store = "128")] +#[cfg(target_has_atomic = "128")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicI128 {} -#[cfg(target_has_atomic_load_store = "ptr")] +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] impl RefUnwindSafe for atomic::AtomicUsize {} -#[cfg(target_has_atomic_load_store = "8")] +#[cfg(target_has_atomic = "8")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicU8 {} -#[cfg(target_has_atomic_load_store = "16")] +#[cfg(target_has_atomic = "16")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicU16 {} -#[cfg(target_has_atomic_load_store = "32")] +#[cfg(target_has_atomic = "32")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicU32 {} -#[cfg(target_has_atomic_load_store = "64")] +#[cfg(target_has_atomic = "64")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicU64 {} -#[cfg(target_has_atomic_load_store = "128")] +#[cfg(target_has_atomic = "128")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicU128 {} -#[cfg(target_has_atomic_load_store = "8")] +#[cfg(target_has_atomic = "8")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] impl RefUnwindSafe for atomic::AtomicBool {} -#[cfg(target_has_atomic_load_store = "ptr")] +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] impl RefUnwindSafe for atomic::AtomicPtr {} diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 619b182019081..28fb40244043e 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -12,13 +12,12 @@ use core::panic::{BoxMeUp, PanicInfo, Location}; use crate::any::Any; use crate::fmt; use crate::intrinsics; -use crate::mem::{self, ManuallyDrop}; +use crate::mem; +use crate::ptr; use crate::raw; -use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::stdio::panic_output; use crate::sys_common::rwlock::RWLock; -use crate::sys_common::{thread_info, util}; -use crate::sys_common::backtrace::{self, RustBacktrace}; +use crate::sys_common::{thread_info, util, backtrace}; use crate::thread; #[cfg(not(test))] @@ -159,10 +158,16 @@ pub fn take_hook() -> Box) + 'static + Sync + Send> { fn default_hook(info: &PanicInfo<'_>) { // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. - let backtrace_env = if update_panic_count(0) >= 2 { - RustBacktrace::Print(backtrace_rs::PrintFmt::Full) + let log_backtrace = if cfg!(feature = "backtrace") { + let panics = update_panic_count(0); + + if panics >= 2 { + Some(backtrace_rs::PrintFmt::Full) + } else { + backtrace::log_enabled() + } } else { - backtrace::rust_backtrace_env() + None }; // The current implementation always returns `Some`. @@ -182,16 +187,16 @@ fn default_hook(info: &PanicInfo<'_>) { let _ = writeln!(err, "thread '{}' panicked at '{}', {}", name, msg, location); - static FIRST_PANIC: AtomicBool = AtomicBool::new(true); + if cfg!(feature = "backtrace") { + use crate::sync::atomic::{AtomicBool, Ordering}; + + static FIRST_PANIC: AtomicBool = AtomicBool::new(true); - match backtrace_env { - RustBacktrace::Print(format) => drop(backtrace::print(err, format)), - RustBacktrace::Disabled => {} - RustBacktrace::RuntimeDisabled => { - if FIRST_PANIC.swap(false, Ordering::SeqCst) { - let _ = writeln!(err, "note: run with `RUST_BACKTRACE=1` \ - environment variable to display a backtrace."); - } + if let Some(format) = log_backtrace { + let _ = backtrace::print(err, format); + } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) { + let _ = writeln!(err, "note: run with `RUST_BACKTRACE=1` \ + environment variable to display a backtrace."); } } }; @@ -217,7 +222,7 @@ pub fn update_panic_count(amt: isize) -> usize { PANIC_COUNT.with(|c| { let next = (c.get() as isize + amt) as usize; c.set(next); - next + return next }) } @@ -226,9 +231,10 @@ pub use realstd::rt::update_panic_count; /// Invoke a closure, capturing the cause of an unwinding panic if one occurs. pub unsafe fn r#try R>(f: F) -> Result> { + #[allow(unions_with_drop_fields)] union Data { - f: ManuallyDrop, - r: ManuallyDrop, + f: F, + r: R, } // We do some sketchy operations with ownership here for the sake of @@ -259,7 +265,7 @@ pub unsafe fn r#try R>(f: F) -> Result> let mut any_data = 0; let mut any_vtable = 0; let mut data = Data { - f: ManuallyDrop::new(f) + f, }; let r = __rust_maybe_catch_panic(do_call::, @@ -269,7 +275,7 @@ pub unsafe fn r#try R>(f: F) -> Result> return if r == 0 { debug_assert!(update_panic_count(0) == 0); - Ok(ManuallyDrop::into_inner(data.r)) + Ok(data.r) } else { update_panic_count(-1); debug_assert!(update_panic_count(0) == 0); @@ -282,9 +288,8 @@ pub unsafe fn r#try R>(f: F) -> Result> fn do_call R, R>(data: *mut u8) { unsafe { let data = data as *mut Data; - let data = &mut (*data); - let f = ManuallyDrop::take(&mut data.f); - data.r = ManuallyDrop::new(f()); + let f = ptr::read(&mut (*data).f); + ptr::write(&mut (*data).r, f()); } } } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 6d6bc760649e0..fd6ff1032bb81 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1363,24 +1363,20 @@ impl PathBuf { } fn _set_extension(&mut self, extension: &OsStr) -> bool { - let file_stem = match self.file_stem() { - None => return false, - Some(f) => os_str_as_u8_slice(f), + if self.file_name().is_none() { + return false; + } + + let mut stem = match self.file_stem() { + Some(stem) => stem.to_os_string(), + None => OsString::new(), }; - // truncate until right after the file stem - let end_file_stem = file_stem[file_stem.len()..].as_ptr() as usize; - let start = os_str_as_u8_slice(&self.inner).as_ptr() as usize; - let v = self.as_mut_vec(); - v.truncate(end_file_stem.wrapping_sub(start)); - - // add the new extension, if any - let new = os_str_as_u8_slice(extension); - if !new.is_empty() { - v.reserve_exact(new.len() + 1); - v.push(b'.'); - v.extend_from_slice(new); + if !os_str_as_u8_slice(extension).is_empty() { + stem.push("."); + stem.push(extension); } + self.set_file_name(&stem); true } @@ -1631,7 +1627,7 @@ impl<'a> From> for PathBuf { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { - /// Converts a `PathBuf` into an `Arc` by moving the `PathBuf` data into a new `Arc` buffer. + /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: PathBuf) -> Arc { let arc: Arc = Arc::from(s.into_os_string()); @@ -1641,7 +1637,7 @@ impl From for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<&Path> for Arc { - /// Converts a `Path` into an `Arc` by copying the `Path` data into a new `Arc` buffer. + /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: &Path) -> Arc { let arc: Arc = Arc::from(s.as_os_str()); @@ -1651,7 +1647,7 @@ impl From<&Path> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { - /// Converts a `PathBuf` into an `Rc` by moving the `PathBuf` data into a new `Rc` buffer. + /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: PathBuf) -> Rc { let rc: Rc = Rc::from(s.into_os_string()); @@ -1661,7 +1657,7 @@ impl From for Rc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<&Path> for Rc { - /// Converts a `Path` into an `Rc` by copying the `Path` data into a new `Rc` buffer. + /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: &Path) -> Rc { let rc: Rc = Rc::from(s.as_os_str()); @@ -2223,7 +2219,6 @@ impl Path { /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] pub fn join>(&self, path: P) -> PathBuf { self._join(path.as_ref()) } diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index a72951c034610..3e389c40fbc01 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -426,12 +426,14 @@ mod prim_unit { } /// /// use std::mem; /// -/// unsafe { -/// let my_num: *mut i32 = libc::malloc(mem::size_of::()) as *mut i32; -/// if my_num.is_null() { -/// panic!("failed to allocate memory"); +/// fn main() { +/// unsafe { +/// let my_num: *mut i32 = libc::malloc(mem::size_of::()) as *mut i32; +/// if my_num.is_null() { +/// panic!("failed to allocate memory"); +/// } +/// libc::free(my_num as *mut libc::c_void); /// } -/// libc::free(my_num as *mut libc::c_void); /// } /// ``` /// diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 4b0cf8312f189..da136ca6bf68d 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1488,12 +1488,12 @@ impl Child { /// } /// /// fn main() { -/// std::process::exit(match run_app() { -/// Ok(_) => 0, -/// Err(err) => { -/// eprintln!("error: {:?}", err); -/// 1 -/// } +/// ::std::process::exit(match run_app() { +/// Ok(_) => 0, +/// Err(err) => { +/// eprintln!("error: {:?}", err); +/// 1 +/// } /// }); /// } /// ``` diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 63e35d5ed919a..cf45eb0daba39 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -44,9 +44,12 @@ fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindS sys::args::init(argc, argv); // Let's run some code! + #[cfg(feature = "backtrace")] let exit_code = panic::catch_unwind(|| { sys_common::backtrace::__rust_begin_short_backtrace(move || main()) }); + #[cfg(not(feature = "backtrace"))] + let exit_code = panic::catch_unwind(move || main()); sys_common::cleanup(); exit_code.unwrap_or(101) as isize diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index c2884a28f3ccd..69ecd201063b0 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1581,6 +1581,10 @@ impl error::Error for SendError { fn description(&self) -> &str { "sending on a closed channel" } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1620,6 +1624,10 @@ impl error::Error for TrySendError { } } } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } } #[stable(feature = "mpsc_error_conversions", since = "1.24.0")] @@ -1644,6 +1652,10 @@ impl error::Error for RecvError { fn description(&self) -> &str { "receiving on a closed channel" } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1673,6 +1685,10 @@ impl error::Error for TryRecvError { } } } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } } #[stable(feature = "mpsc_error_conversions", since = "1.24.0")] @@ -1710,6 +1726,10 @@ impl error::Error for RecvTimeoutError { } } } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } } #[stable(feature = "mpsc_error_conversions", since = "1.24.0")] diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index e28fbca7fa1c2..e529b8c4227fa 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -60,9 +60,10 @@ use crate::thread::{self, Thread}; /// A synchronization primitive which can be used to run a one-time global /// initialization. Useful for one-time initialization for FFI or related -/// functionality. This type can only be constructed with the [`Once::new`] -/// constructor. +/// functionality. This type can only be constructed with the [`ONCE_INIT`] +/// value or the equivalent [`Once::new`] constructor. /// +/// [`ONCE_INIT`]: constant.ONCE_INIT.html /// [`Once::new`]: struct.Once.html#method.new /// /// # Examples diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs index d7e733b7fa032..952ba40ee87a9 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -10,8 +10,7 @@ // fallback implementation to use as well. // // Due to rust-lang/rust#18804, make sure this is not generic! -#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit", target_os = "redox", - target_os = "emscripten"))] +#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit", target_os = "redox"))] 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; diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index ba611a6b7e7b9..ac43526b50f2c 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -71,7 +71,22 @@ impl FileDesc { #[cfg(target_os = "android")] use super::android::cvt_pread64; - #[cfg(not(target_os = "android"))] + #[cfg(target_os = "emscripten")] + unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: usize, offset: i64) + -> io::Result + { + use crate::convert::TryInto; + use libc::pread64; + // pread64 on emscripten actually takes a 32 bit offset + if let Ok(o) = offset.try_into() { + cvt(pread64(fd, buf, count, o)) + } else { + Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot pread >2GB")) + } + } + + #[cfg(not(any(target_os = "android", target_os = "emscripten")))] unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: usize, offset: i64) -> io::Result { @@ -113,7 +128,22 @@ impl FileDesc { #[cfg(target_os = "android")] use super::android::cvt_pwrite64; - #[cfg(not(target_os = "android"))] + #[cfg(target_os = "emscripten")] + unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: usize, offset: i64) + -> io::Result + { + use crate::convert::TryInto; + use libc::pwrite64; + // pwrite64 on emscripten actually takes a 32 bit offset + if let Ok(o) = offset.try_into() { + cvt(pwrite64(fd, buf, count, o)) + } else { + Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot pwrite >2GB")) + } + } + + #[cfg(not(any(target_os = "android", target_os = "emscripten")))] unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: usize, offset: i64) -> io::Result { diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 5e1f10c03ceda..3b1eb86b84fe1 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -41,151 +41,11 @@ pub use crate::sys_common::fs::remove_dir_all; pub struct File(FileDesc); -// FIXME: This should be available on Linux with all `target_arch` and `target_env`. -// https://github.com/rust-lang/libc/issues/1545 -macro_rules! cfg_has_statx { - ({ $($then_tt:tt)* } else { $($else_tt:tt)* }) => { - cfg_if::cfg_if! { - if #[cfg(all(target_os = "linux", target_env = "gnu", any( - target_arch = "x86", - target_arch = "arm", - // target_arch = "mips", - target_arch = "powerpc", - target_arch = "x86_64", - // target_arch = "aarch64", - target_arch = "powerpc64", - // target_arch = "mips64", - // target_arch = "s390x", - target_arch = "sparc64", - )))] { - $($then_tt)* - } else { - $($else_tt)* - } - } - }; - ($($block_inner:tt)*) => { - #[cfg(all(target_os = "linux", target_env = "gnu", any( - target_arch = "x86", - target_arch = "arm", - // target_arch = "mips", - target_arch = "powerpc", - target_arch = "x86_64", - // target_arch = "aarch64", - target_arch = "powerpc64", - // target_arch = "mips64", - // target_arch = "s390x", - target_arch = "sparc64", - )))] - { - $($block_inner)* - } - }; +#[derive(Clone)] +pub struct FileAttr { + stat: stat64, } -cfg_has_statx! {{ - #[derive(Clone)] - pub struct FileAttr { - stat: stat64, - statx_extra_fields: Option, - } - - #[derive(Clone)] - struct StatxExtraFields { - // This is needed to check if btime is supported by the filesystem. - stx_mask: u32, - stx_btime: libc::statx_timestamp, - } - - // We prefer `statx` on Linux if available, which contains file creation time. - // Default `stat64` contains no creation time. - unsafe fn try_statx( - fd: c_int, - path: *const libc::c_char, - flags: i32, - mask: u32, - ) -> Option> { - use crate::sync::atomic::{AtomicU8, Ordering}; - - // Linux kernel prior to 4.11 or glibc prior to glibc 2.28 don't support `statx` - // We store the availability in global to avoid unnecessary syscalls. - // 0: Unknown - // 1: Not available - // 2: Available - static STATX_STATE: AtomicU8 = AtomicU8::new(0); - syscall! { - fn statx( - fd: c_int, - pathname: *const libc::c_char, - flags: c_int, - mask: libc::c_uint, - statxbuf: *mut libc::statx - ) -> c_int - } - - match STATX_STATE.load(Ordering::Relaxed) { - 0 => { - // It is a trick to call `statx` with NULL pointers to check if the syscall - // is available. According to the manual, it is expected to fail with EFAULT. - // We do this mainly for performance, since it is nearly hundreds times - // faster than a normal successfull call. - let err = cvt(statx(0, ptr::null(), 0, libc::STATX_ALL, ptr::null_mut())) - .err() - .and_then(|e| e.raw_os_error()); - // We don't check `err == Some(libc::ENOSYS)` because the syscall may be limited - // and returns `EPERM`. Listing all possible errors seems not a good idea. - // See: https://github.com/rust-lang/rust/issues/65662 - if err != Some(libc::EFAULT) { - STATX_STATE.store(1, Ordering::Relaxed); - return None; - } - STATX_STATE.store(2, Ordering::Relaxed); - } - 1 => return None, - _ => {} - } - - let mut buf: libc::statx = mem::zeroed(); - if let Err(err) = cvt(statx(fd, path, flags, mask, &mut buf)) { - return Some(Err(err)); - } - - // We cannot fill `stat64` exhaustively because of private padding fields. - let mut stat: stat64 = mem::zeroed(); - // `c_ulong` on gnu-mips, `dev_t` otherwise - stat.st_dev = libc::makedev(buf.stx_dev_major, buf.stx_dev_minor) as _; - stat.st_ino = buf.stx_ino as libc::ino64_t; - stat.st_nlink = buf.stx_nlink as libc::nlink_t; - stat.st_mode = buf.stx_mode as libc::mode_t; - stat.st_uid = buf.stx_uid as libc::uid_t; - stat.st_gid = buf.stx_gid as libc::gid_t; - stat.st_rdev = libc::makedev(buf.stx_rdev_major, buf.stx_rdev_minor) as _; - stat.st_size = buf.stx_size as off64_t; - stat.st_blksize = buf.stx_blksize as libc::blksize_t; - stat.st_blocks = buf.stx_blocks as libc::blkcnt64_t; - stat.st_atime = buf.stx_atime.tv_sec as libc::time_t; - // `i64` on gnu-x86_64-x32, `c_ulong` otherwise. - stat.st_atime_nsec = buf.stx_atime.tv_nsec as _; - stat.st_mtime = buf.stx_mtime.tv_sec as libc::time_t; - stat.st_mtime_nsec = buf.stx_mtime.tv_nsec as _; - stat.st_ctime = buf.stx_ctime.tv_sec as libc::time_t; - stat.st_ctime_nsec = buf.stx_ctime.tv_nsec as _; - - let extra = StatxExtraFields { - stx_mask: buf.stx_mask, - stx_btime: buf.stx_btime, - }; - - Some(Ok(FileAttr { stat, statx_extra_fields: Some(extra) })) - } - -} else { - #[derive(Clone)] - pub struct FileAttr { - stat: stat64, - } -}} - // all DirEntry's will have a reference to this struct struct InnerReadDir { dirp: Dir, @@ -237,20 +97,6 @@ pub struct FileType { mode: mode_t } #[derive(Debug)] pub struct DirBuilder { mode: mode_t } -cfg_has_statx! {{ - impl FileAttr { - fn from_stat64(stat: stat64) -> Self { - Self { stat, statx_extra_fields: None } - } - } -} else { - impl FileAttr { - fn from_stat64(stat: stat64) -> Self { - Self { stat } - } - } -}} - impl FileAttr { pub fn size(&self) -> u64 { self.stat.st_size as u64 } pub fn perm(&self) -> FilePermissions { @@ -318,22 +164,6 @@ impl FileAttr { target_os = "macos", target_os = "ios")))] pub fn created(&self) -> io::Result { - cfg_has_statx! { - if let Some(ext) = &self.statx_extra_fields { - return if (ext.stx_mask & libc::STATX_BTIME) != 0 { - Ok(SystemTime::from(libc::timespec { - tv_sec: ext.stx_btime.tv_sec as libc::time_t, - tv_nsec: ext.stx_btime.tv_nsec as _, - })) - } else { - Err(io::Error::new( - io::ErrorKind::Other, - "creation time is not available for the filesystem", - )) - }; - } - } - Err(io::Error::new(io::ErrorKind::Other, "creation time is not available on this platform \ currently")) @@ -476,25 +306,12 @@ impl DirEntry { #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))] pub fn metadata(&self) -> io::Result { - let fd = cvt(unsafe { dirfd(self.dir.inner.dirp.0) })?; - let name = self.entry.d_name.as_ptr(); - - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - fd, - name, - libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_ALL, - ) } { - return ret; - } - } - + let fd = cvt(unsafe {dirfd(self.dir.inner.dirp.0)})?; let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { - fstatat64(fd, name, &mut stat, libc::AT_SYMLINK_NOFOLLOW) + fstatat64(fd, self.entry.d_name.as_ptr(), &mut stat, libc::AT_SYMLINK_NOFOLLOW) })?; - Ok(FileAttr::from_stat64(stat)) + Ok(FileAttr { stat }) } #[cfg(not(any(target_os = "linux", target_os = "emscripten", target_os = "android")))] @@ -700,24 +517,11 @@ impl File { } pub fn file_attr(&self) -> io::Result { - let fd = self.0.raw(); - - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - fd, - b"\0" as *const _ as *const libc::c_char, - libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_ALL, - ) } { - return ret; - } - } - let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { - fstat64(fd, &mut stat) + fstat64(self.0.raw(), &mut stat) })?; - Ok(FileAttr::from_stat64(stat)) + Ok(FileAttr { stat }) } pub fn fsync(&self) -> io::Result<()> { @@ -798,6 +602,8 @@ impl File { SeekFrom::End(off) => (libc::SEEK_END, off), SeekFrom::Current(off) => (libc::SEEK_CUR, off), }; + #[cfg(target_os = "emscripten")] + let pos = pos as i32; let n = cvt(unsafe { lseek64(self.0.raw(), pos, whence) })?; Ok(n as u64) } @@ -992,44 +798,20 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { pub fn stat(p: &Path) -> io::Result { let p = cstr(p)?; - - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - libc::AT_FDCWD, - p.as_ptr(), - libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_ALL, - ) } { - return ret; - } - } - let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?; - Ok(FileAttr::from_stat64(stat)) + Ok(FileAttr { stat }) } pub fn lstat(p: &Path) -> io::Result { let p = cstr(p)?; - - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - libc::AT_FDCWD, - p.as_ptr(), - libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_ALL, - ) } { - return ret; - } - } - let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?; - Ok(FileAttr::from_stat64(stat)) + Ok(FileAttr { stat }) } pub fn canonicalize(p: &Path) -> io::Result { diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index be112f6fc0329..c5be17633025f 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -8,7 +8,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { mem::size_of_val(&v)); imp::fill_bytes(view); } - v + return v } #[cfg(all(unix, diff --git a/src/libstd/sys/vxworks/fs.rs b/src/libstd/sys/vxworks/fs.rs index adb08d8005ad4..51fdb1c0e55ec 100644 --- a/src/libstd/sys/vxworks/fs.rs +++ b/src/libstd/sys/vxworks/fs.rs @@ -400,27 +400,13 @@ impl FromInner for File { impl fmt::Debug for File { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fn get_path(fd: c_int) -> Option { - let mut buf = vec![0;libc::PATH_MAX as usize]; - let n = unsafe { libc::ioctl(fd, libc::FIOGETNAME, buf.as_ptr()) }; - if n == -1 { - return None; - } - let l = buf.iter().position(|&c| c == 0).unwrap(); - buf.truncate(l as usize); - Some(PathBuf::from(OsString::from_vec(buf))) + fn get_path(_fd: c_int) -> Option { + // FIXME(#:(): implement this for VxWorks + None } - fn get_mode(fd: c_int) -> Option<(bool, bool)> { - let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) }; - if mode == -1 { - return None; - } - match mode & libc::O_ACCMODE { - libc::O_RDONLY => Some((true, false)), - libc::O_RDWR => Some((true, true)), - libc::O_WRONLY => Some((false, true)), - _ => None - } + fn get_mode(_fd: c_int) -> Option<(bool, bool)> { + // FIXME(#:(): implement this for VxWorks + None } let fd = self.0.raw(); diff --git a/src/libstd/sys/vxworks/rwlock.rs b/src/libstd/sys/vxworks/rwlock.rs index 19b123f2b6131..718f422ed11e6 100644 --- a/src/libstd/sys/vxworks/rwlock.rs +++ b/src/libstd/sys/vxworks/rwlock.rs @@ -25,7 +25,7 @@ impl RWLock { let r = libc::pthread_rwlock_rdlock(self.inner.get()); if r == libc::EAGAIN { panic!("rwlock maximum reader count exceeded"); - } else if r == libc::EDEADLK || (r == 0 && *self.write_locked.get()) { + } else if r == libc::EDEADLK || *self.write_locked.get() { if r == 0 { self.raw_unlock(); } diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index 6ce41420284e5..28a504f197974 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -31,10 +31,10 @@ impl Thread { let nanos = dur.as_nanos(); assert!(nanos <= u64::max_value() as u128); - const USERDATA: wasi::Userdata = 0x0123_45678; + const CLOCK_ID: wasi::Userdata = 0x0123_45678; let clock = wasi::raw::__wasi_subscription_u_clock_t { - identifier: 0, + identifier: CLOCK_ID, clock_id: wasi::CLOCK_MONOTONIC, timeout: nanos as u64, precision: 0, @@ -42,7 +42,7 @@ impl Thread { }; let in_ = [wasi::Subscription { - userdata: USERDATA, + userdata: 0, type_: wasi::EVENTTYPE_CLOCK, u: wasi::raw::__wasi_subscription_u { clock: clock }, }]; @@ -53,7 +53,7 @@ impl Thread { }; match (res, event) { (Ok(1), wasi::Event { - userdata: USERDATA, + userdata: CLOCK_ID, error: 0, type_: wasi::EVENTTYPE_CLOCK, .. diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 4160123c9a2ab..204f6af5fc1a0 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -412,7 +412,7 @@ impl File { pub fn duplicate(&self) -> io::Result { Ok(File { - handle: self.handle.duplicate(0, false, c::DUPLICATE_SAME_ACCESS)?, + handle: self.handle.duplicate(0, true, c::DUPLICATE_SAME_ACCESS)?, }) } diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index 3986cda1a5047..3e5aa69335461 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -46,7 +46,7 @@ impl Handle { pub fn into_raw(self) -> c::HANDLE { let ret = self.raw(); mem::forget(self); - ret + return ret; } } diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 79dec1adf4bc8..37cbdcefcedcc 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -144,7 +144,7 @@ fn kind() -> Kind { Some(..) => Kind::SRWLock, }; KIND.store(ret as usize, Ordering::SeqCst); - ret + return ret; } pub struct ReentrantMutex { inner: UnsafeCell> } diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 096b7bea8a5f1..8658deb854635 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -257,7 +257,7 @@ impl Stdio { let ret = io.duplicate(0, true, c::DUPLICATE_SAME_ACCESS); io.into_raw(); - ret + return ret } Err(..) => Ok(Handle::new(c::INVALID_HANDLE_VALUE)), } @@ -472,8 +472,9 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result> { cmd.push('"' as u16); } + let mut iter = arg.encode_wide(); let mut backslashes: usize = 0; - for x in arg.encode_wide() { + while let Some(x) = iter.next() { if x == '\\' as u16 { backslashes += 1; } else { diff --git a/src/libstd/sys/windows/rand.rs b/src/libstd/sys/windows/rand.rs index 993831bec1886..c9bcb5d741514 100644 --- a/src/libstd/sys/windows/rand.rs +++ b/src/libstd/sys/windows/rand.rs @@ -13,7 +13,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); } - v + return v } #[cfg(target_vendor = "uwp")] diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs index 728257cdd4bb1..4c9734fa0aa61 100644 --- a/src/libstd/sys/windows/thread_local.rs +++ b/src/libstd/sys/windows/thread_local.rs @@ -52,7 +52,7 @@ pub unsafe fn create(dtor: Option) -> Key { if let Some(f) = dtor { register_dtor(key, f); } - key + return key; } #[inline] diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs index bd533c93d434c..e0f0e3a1a45b9 100644 --- a/src/libstd/sys/windows/time.rs +++ b/src/libstd/sys/windows/time.rs @@ -80,7 +80,7 @@ impl SystemTime { unsafe { let mut t: SystemTime = mem::zeroed(); c::GetSystemTimeAsFileTime(&mut t.t); - t + return t } } @@ -228,7 +228,7 @@ mod perf_counter { FREQUENCY = frequency; STATE.store(2, SeqCst); } - frequency + return frequency; } } diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 9c406ec39cc45..01711d415d86c 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -7,7 +7,6 @@ use crate::io; use crate::borrow::Cow; use crate::io::prelude::*; use crate::path::{self, Path, PathBuf}; -use crate::sync::atomic::{self, Ordering}; use crate::sys::mutex::Mutex; use backtrace_rs::{BacktraceFmt, BytesOrWideString, PrintFmt}; @@ -116,10 +115,8 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: Ok(()) } -/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that -/// this is only inline(never) when backtraces in libstd are enabled, otherwise -/// it's fine to optimize away. -#[cfg_attr(feature = "backtrace", inline(never))] +/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. +#[inline(never)] pub fn __rust_begin_short_backtrace(f: F) -> T where F: FnOnce() -> T, @@ -129,49 +126,42 @@ where f() } -pub enum RustBacktrace { - Print(PrintFmt), - Disabled, - RuntimeDisabled, -} - // 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 rust_backtrace_env() -> RustBacktrace { - // If the `backtrace` feature of this crate isn't enabled quickly return - // `None` so this can be constant propagated all over the place to turn - // optimize away callers. - if !cfg!(feature = "backtrace") { - return RustBacktrace::Disabled; - } +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 RustBacktrace::Print(PrintFmt::Full); + return Some(PrintFmt::Full); } static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0); match ENABLED.load(Ordering::SeqCst) { 0 => {} - 1 => return RustBacktrace::RuntimeDisabled, - 2 => return RustBacktrace::Print(PrintFmt::Short), - _ => return RustBacktrace::Print(PrintFmt::Full), + 1 => return None, + 2 => return Some(PrintFmt::Short), + _ => return Some(PrintFmt::Full), } - let (format, cache) = env::var_os("RUST_BACKTRACE") - .map(|x| { - if &x == "0" { - (RustBacktrace::RuntimeDisabled, 1) - } else if &x == "full" { - (RustBacktrace::Print(PrintFmt::Full), 3) - } else { - (RustBacktrace::Print(PrintFmt::Short), 2) - } - }) - .unwrap_or((RustBacktrace::RuntimeDisabled, 1)); - ENABLED.store(cache, Ordering::SeqCst); - format + let val = env::var_os("RUST_BACKTRACE").and_then(|x| { + if &x == "0" { + None + } else if &x == "full" { + Some(PrintFmt::Full) + } else { + Some(PrintFmt::Short) + } + }); + ENABLED.store( + match val { + Some(v) => v as isize, + None => 1, + }, + Ordering::SeqCst, + ); + val } /// Prints the filename of the backtrace frame. diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs index 3753269adfe45..d734f412bf886 100644 --- a/src/libstd/sys_common/os_str_bytes.rs +++ b/src/libstd/sys_common/os_str_bytes.rs @@ -193,7 +193,7 @@ impl Slice { pub trait OsStringExt { /// Creates an [`OsString`] from a byte vector. /// - /// See the module documentation for an example. + /// See the module docmentation for an example. /// /// [`OsString`]: ../../../ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] @@ -201,7 +201,7 @@ pub trait OsStringExt { /// Yields the underlying byte vector of this [`OsString`]. /// - /// See the module documentation for an example. + /// See the module docmentation for an example. /// /// [`OsString`]: ../../../ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] @@ -226,14 +226,14 @@ pub trait OsStrExt { #[stable(feature = "rust1", since = "1.0.0")] /// Creates an [`OsStr`] from a byte slice. /// - /// See the module documentation for an example. + /// See the module docmentation for an example. /// /// [`OsStr`]: ../../../ffi/struct.OsStr.html fn from_bytes(slice: &[u8]) -> &Self; /// Gets the underlying byte view of the [`OsStr`] slice. /// - /// See the module documentation for an example. + /// See the module docmentation for an example. /// /// [`OsStr`]: ../../../ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index cfaab4e22e9cf..e92c0d1c58e41 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -509,8 +509,9 @@ pub mod os { pub unsafe fn get(&'static self, init: fn() -> T) -> Option<&'static T> { let ptr = self.os.get() as *mut Value; if ptr as usize > 1 { - if let Some(ref value) = (*ptr).inner.get() { - return Some(value); + match (*ptr).inner.get() { + Some(ref value) => return Some(value), + None => {}, } } self.try_initialize(init) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 0ffa6ace2e4d2..764041d2f4239 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -465,9 +465,12 @@ impl Builder { } thread_info::set(imp::guard::current(), their_thread); + #[cfg(feature = "backtrace")] let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { crate::sys_common::backtrace::__rust_begin_short_backtrace(f) })); + #[cfg(not(feature = "backtrace"))] + let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f)); *their_packet.get() = Some(try_result); }; diff --git a/src/libstd/time.rs b/src/libstd/time.rs index e1ae01b602a8d..3bf2b8be1fe8e 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -15,10 +15,10 @@ use crate::cmp; use crate::error::Error; use crate::fmt; -use crate::ops::{Add, AddAssign, Sub, SubAssign}; +use crate::ops::{Add, Sub, AddAssign, SubAssign}; use crate::sys::time; -use crate::sys_common::mutex::Mutex; use crate::sys_common::FromInner; +use crate::sys_common::mutex::Mutex; #[stable(feature = "time", since = "1.3.0")] pub use core::time::Duration; @@ -216,17 +216,17 @@ impl Instant { // * https://bugzilla.mozilla.org/show_bug.cgi?id=1487778 - a similar // Firefox bug // - // It seems that this just happens a lot in the wild. - // We're seeing panics across various platforms where consecutive calls + // It simply seems that this it just happens so that a lot in the wild + // we're seeing panics across various platforms where consecutive calls // to `Instant::now`, such as via the `elapsed` function, are panicking // as they're going backwards. Placed here is a last-ditch effort to try // to fix things up. We keep a global "latest now" instance which is // returned instead of what the OS says if the OS goes backwards. // - // To hopefully mitigate the impact of this, a few platforms are + // To hopefully mitigate the impact of this though a few platforms are // whitelisted as "these at least haven't gone backwards yet". if time::Instant::actually_monotonic() { - return Instant(os_now); + return Instant(os_now) } static LOCK: Mutex = Mutex::new(); @@ -353,7 +353,8 @@ impl Add for Instant { /// /// [`checked_add`]: ../../std/time/struct.Instant.html#method.checked_add fn add(self, other: Duration) -> Instant { - self.checked_add(other).expect("overflow when adding duration to instant") + self.checked_add(other) + .expect("overflow when adding duration to instant") } } @@ -369,7 +370,8 @@ impl Sub for Instant { type Output = Instant; fn sub(self, other: Duration) -> Instant { - self.checked_sub(other).expect("overflow when subtracting duration from instant") + self.checked_sub(other) + .expect("overflow when subtracting duration from instant") } } @@ -462,7 +464,8 @@ impl SystemTime { /// println!("{:?}", difference); /// ``` #[stable(feature = "time2", since = "1.8.0")] - pub fn duration_since(&self, earlier: SystemTime) -> Result { + pub fn duration_since(&self, earlier: SystemTime) + -> Result { self.0.sub_time(&earlier.0).map_err(SystemTimeError) } @@ -529,7 +532,8 @@ impl Add for SystemTime { /// /// [`checked_add`]: ../../std/time/struct.SystemTime.html#method.checked_add fn add(self, dur: Duration) -> SystemTime { - self.checked_add(dur).expect("overflow when adding duration to instant") + self.checked_add(dur) + .expect("overflow when adding duration to instant") } } @@ -545,7 +549,8 @@ impl Sub for SystemTime { type Output = SystemTime; fn sub(self, dur: Duration) -> SystemTime { - self.checked_sub(dur).expect("overflow when subtracting duration from instant") + self.checked_sub(dur) + .expect("overflow when subtracting duration from instant") } } @@ -621,9 +626,7 @@ impl SystemTimeError { #[stable(feature = "time2", since = "1.8.0")] impl Error for SystemTimeError { - fn description(&self) -> &str { - "other time was not earlier than self" - } + fn description(&self) -> &str { "other time was not earlier than self" } } #[stable(feature = "time2", since = "1.8.0")] @@ -641,16 +644,17 @@ impl FromInner for SystemTime { #[cfg(test)] mod tests { - use super::{Duration, Instant, SystemTime, UNIX_EPOCH}; + use super::{Instant, SystemTime, Duration, UNIX_EPOCH}; macro_rules! assert_almost_eq { - ($a:expr, $b:expr) => {{ + ($a:expr, $b:expr) => ({ let (a, b) = ($a, $b); if a != b { - let (a, b) = if a > b { (a, b) } else { (b, a) }; - assert!(a - Duration::new(0, 1000) <= b, "{:?} is not almost equal to {:?}", a, b); + let (a, b) = if a > b {(a, b)} else {(b, a)}; + assert!(a - Duration::new(0, 1000) <= b, + "{:?} is not almost equal to {:?}", a, b); } - }}; + }) } #[test] @@ -725,7 +729,7 @@ mod tests { fn instant_saturating_duration_since_nopanic() { let a = Instant::now(); let ret = (a - Duration::new(1, 0)).saturating_duration_since(a); - assert_eq!(ret, Duration::new(0, 0)); + assert_eq!(ret, Duration::new(0,0)); } #[test] @@ -751,14 +755,15 @@ mod tests { let second = Duration::new(1, 0); assert_almost_eq!(a.duration_since(a - second).unwrap(), second); - assert_almost_eq!(a.duration_since(a + second).unwrap_err().duration(), second); + assert_almost_eq!(a.duration_since(a + second).unwrap_err() + .duration(), second); assert_almost_eq!(a - second + second, a); assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a); let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0); - let one_second_from_epoch2 = - UNIX_EPOCH + Duration::new(0, 500_000_000) + Duration::new(0, 500_000_000); + let one_second_from_epoch2 = UNIX_EPOCH + Duration::new(0, 500_000_000) + + Duration::new(0, 500_000_000); assert_eq!(one_second_from_epoch, one_second_from_epoch2); // checked_add_duration will not panic on overflow diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml index d8de21cc6778f..196cf4d9dfae8 100644 --- a/src/libsyntax/Cargo.toml +++ b/src/libsyntax/Cargo.toml @@ -18,7 +18,6 @@ lazy_static = "1.0.0" syntax_pos = { path = "../libsyntax_pos" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_data_structures = { path = "../librustc_data_structures" } -rustc_index = { path = "../librustc_index" } rustc_lexer = { path = "../librustc_lexer" } rustc_target = { path = "../librustc_target" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 51a62cd065843..a7f035dc9ecc7 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2,29 +2,31 @@ pub use GenericArgs::*; pub use UnsafeSource::*; +pub use crate::symbol::{Ident, Symbol as Name}; pub use crate::util::parser::ExprPrecedence; +use crate::ext::hygiene::ExpnId; use crate::parse::token::{self, DelimToken}; +use crate::print::pprust; use crate::ptr::P; use crate::source_map::{dummy_spanned, respan, Spanned}; +use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::TokenStream; +use crate::ThinVec; -use rustc_target::spec::abi::Abi; -pub use rustc_target::abi::FloatTy; - -use syntax_pos::{Span, DUMMY_SP, ExpnId}; -use syntax_pos::symbol::{kw, sym, Symbol}; -pub use syntax_pos::symbol::{Ident, Symbol as Name}; - -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; #[cfg(target_arch = "x86_64")] use rustc_data_structures::static_assert_size; +use rustc_target::spec::abi::Abi; +use syntax_pos::{Span, DUMMY_SP}; + use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::thin_vec::ThinVec; use rustc_serialize::{self, Decoder, Encoder}; use std::fmt; +pub use rustc_target::abi::FloatTy; + #[cfg(test)] mod tests; @@ -68,7 +70,7 @@ impl fmt::Display for Lifetime { /// along with a bunch of supporting information. /// /// E.g., `std::cmp::PartialEq`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Path { pub span: Span, /// The segments in the path: the things separated by `::`. @@ -84,6 +86,18 @@ impl PartialEq for Path { } } +impl fmt::Debug for Path { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "path({})", pprust::path_to_string(self)) + } +} + +impl fmt::Display for Path { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", pprust::path_to_string(self)) + } +} + impl Path { // Convert a span and an identifier to the corresponding // one-segment path. @@ -227,8 +241,9 @@ impl ParenthesizedArgs { // hack to ensure that we don't try to access the private parts of `NodeId` in this module mod node_id_inner { - use rustc_index::vec::Idx; - rustc_index::newtype_index! { + use rustc_data_structures::indexed_vec::Idx; + use rustc_data_structures::newtype_index; + newtype_index! { pub struct NodeId { ENCODABLE = custom DEBUG_FORMAT = "NodeId({})" @@ -493,13 +508,19 @@ pub struct Block { pub span: Span, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Pat { pub id: NodeId, pub kind: PatKind, pub span: Span, } +impl fmt::Debug for Pat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "pat({}: {})", self.id, pprust::pat_to_string(self)) + } +} + impl Pat { /// Attempt reparsing the pattern as a type. /// This is intended for use by diagnostics. @@ -811,7 +832,7 @@ impl UnOp { } /// A statement -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Stmt { pub id: NodeId, pub kind: StmtKind, @@ -845,7 +866,18 @@ impl Stmt { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +impl fmt::Debug for Stmt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "stmt({}: {})", + self.id.to_string(), + pprust::stmt_to_string(self) + ) + } +} + +#[derive(Clone, RustcEncodable, RustcDecodable)] pub enum StmtKind { /// A local (let) binding. Local(P), @@ -942,7 +974,7 @@ pub struct AnonConst { } /// An expression. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Expr { pub id: NodeId, pub kind: ExprKind, @@ -1069,6 +1101,12 @@ impl Expr { } } +impl fmt::Debug for Expr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "expr({}: {})", self.id, pprust::expr_to_string(self)) + } +} + /// Limit types of a range (inclusive or exclusive) #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] pub enum RangeLimits { @@ -1305,7 +1343,6 @@ impl MacroDef { } } -// Clippy uses Hash and PartialEq #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)] pub enum StrStyle { /// A regular string, like `"foo"`. @@ -1328,7 +1365,6 @@ pub struct Lit { pub span: Span, } -// Clippy uses Hash and PartialEq #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)] pub enum LitIntType { Signed(IntTy), @@ -1339,7 +1375,6 @@ pub enum LitIntType { /// Literal kind. /// /// E.g., `"foo"`, `42`, `12.34`, or `bool`. -// Clippy uses Hash and PartialEq #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)] pub enum LitKind { /// A string literal (`"foo"`). @@ -1626,13 +1661,19 @@ pub enum AssocTyConstraintKind { }, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Ty { pub id: NodeId, pub kind: TyKind, pub span: Span, } +impl fmt::Debug for Ty { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "type({})", pprust::ty_to_string(self)) + } +} + #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct BareFnTy { pub unsafety: Unsafety, @@ -1852,6 +1893,7 @@ impl Param { pub struct FnDecl { pub inputs: Vec, pub output: FunctionRetTy, + pub c_variadic: bool, } impl FnDecl { @@ -1861,12 +1903,6 @@ impl FnDecl { pub fn has_self(&self) -> bool { self.inputs.get(0).map(Param::is_self).unwrap_or(false) } - pub fn c_variadic(&self) -> bool { - self.inputs.last().map(|arg| match arg.ty.kind { - TyKind::CVarArgs => true, - _ => false, - }).unwrap_or(false) - } } /// Is the trait definition an auto trait? @@ -2099,29 +2135,18 @@ impl rustc_serialize::Decodable for AttrId { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct AttrItem { - pub path: Path, - pub tokens: TokenStream, -} - /// Metadata associated with an item. /// Doc-comments are promoted to attributes that have `is_sugared_doc = true`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Attribute { - pub item: AttrItem, pub id: AttrId, pub style: AttrStyle, + pub path: Path, + pub tokens: TokenStream, pub is_sugared_doc: bool, pub span: Span, } -// Compatibility impl to avoid churn, consider removing. -impl std::ops::Deref for Attribute { - type Target = AttrItem; - fn deref(&self) -> &Self::Target { &self.item } -} - /// `TraitRef`s appear in impls. /// /// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 84c86c9651fcf..2a8e6b2cc9510 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -2,9 +2,9 @@ use crate::ast::{self, Attribute, MetaItem, NestedMetaItem}; use crate::early_buffered_lints::BufferedEarlyLintId; +use crate::ext::base::ExtCtxt; use crate::feature_gate::{Features, GatedCfg}; -use crate::print::pprust; -use crate::sess::ParseSess; +use crate::parse::ParseSess; use errors::{Applicability, Handler}; use syntax_pos::hygiene::Transparency; @@ -31,10 +31,6 @@ pub struct AttributeTemplate { } impl AttributeTemplate { - pub fn only_word() -> Self { - Self { word: true, list: None, name_value_str: None } - } - /// Checks that the given meta-item is compatible with this template. fn compatible(&self, meta_item_kind: &ast::MetaItemKind) -> bool { match meta_item_kind { @@ -84,7 +80,7 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) { } } -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)] pub enum InlineAttr { None, Hint, @@ -92,7 +88,7 @@ pub enum InlineAttr { Never, } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)] pub enum OptimizeAttr { None, Speed, @@ -247,11 +243,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, let meta = meta.as_ref().unwrap(); let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { - handle_errors( - sess, - meta.span, - AttrError::MultipleItem(pprust::path_to_string(&meta.path)), - ); + handle_errors(sess, meta.span, AttrError::MultipleItem(meta.path.to_string())); return false } if let Some(v) = meta.value_str() { @@ -279,10 +271,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, handle_errors( sess, mi.span, - AttrError::UnknownMetaItem( - pprust::path_to_string(&mi.path), - expected, - ), + AttrError::UnknownMetaItem(mi.path.to_string(), expected), ); continue 'outer } @@ -373,7 +362,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, sess, meta.span(), AttrError::UnknownMetaItem( - pprust::path_to_string(&mi.path), + mi.path.to_string(), &["feature", "reason", "issue", "soft"] ), ); @@ -445,8 +434,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, sess, meta.span(), AttrError::UnknownMetaItem( - pprust::path_to_string(&mi.path), - &["since", "note"], + mi.path.to_string(), &["since", "note"], ), ); continue 'outer @@ -609,11 +597,8 @@ pub fn eval_condition(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) !eval_condition(mis[0].meta_item().unwrap(), sess, eval) }, _ => { - span_err!( - sess.span_diagnostic, cfg.span, E0537, - "invalid predicate `{}`", - pprust::path_to_string(&cfg.path) - ); + span_err!(sess.span_diagnostic, cfg.span, E0537, + "invalid predicate `{}`", cfg.path); false } } @@ -624,7 +609,8 @@ pub fn eval_condition(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) } } -#[derive(RustcEncodable, RustcDecodable, Clone)] + +#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)] pub struct Deprecation { pub since: Option, pub note: Option, @@ -667,9 +653,7 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { handle_errors( - sess, - meta.span, - AttrError::MultipleItem(pprust::path_to_string(&meta.path)), + sess, meta.span, AttrError::MultipleItem(meta.path.to_string()) ); return false } @@ -707,10 +691,8 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, handle_errors( sess, meta.span(), - AttrError::UnknownMetaItem( - pprust::path_to_string(&mi.path), - &["since", "note"], - ), + AttrError::UnknownMetaItem(mi.path.to_string(), + &["since", "note"]), ); continue 'outer } @@ -748,7 +730,7 @@ pub enum ReprAttr { ReprAlign(u32), } -#[derive(Eq, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] +#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] pub enum IntType { SignedInt(ast::IntTy), UnsignedInt(ast::UintTy) @@ -939,7 +921,14 @@ pub fn find_transparency( (transparency.map_or(fallback, |t| t.0), error) } -pub fn check_builtin_attribute( +pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) { + // All the built-in macro attributes are "words" at the moment. + let template = AttributeTemplate { word: true, list: None, name_value_str: None }; + let attr = ecx.attribute(meta_item.clone()); + check_builtin_attribute(ecx.parse_sess, &attr, name, template); +} + +crate fn check_builtin_attribute( sess: &ParseSess, attr: &ast::Attribute, name: Symbol, template: AttributeTemplate ) { // Some special attributes like `cfg` must be checked diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 27de084ae98ca..122cb7fb12b24 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -9,20 +9,19 @@ pub use StabilityLevel::*; pub use crate::ast::Attribute; use crate::ast; -use crate::ast::{AttrItem, AttrId, AttrStyle, Name, Ident, Path, PathSegment}; +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}; -use crate::parse::lexer::comments::doc_comment_style; +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::PResult; +use crate::parse::{ParseSess, PResult}; use crate::parse::token::{self, Token}; use crate::ptr::P; -use crate::sess::ParseSess; use crate::symbol::{sym, Symbol}; use crate::ThinVec; -use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; +use crate::tokenstream::{TokenStream, TokenTree, DelimSpan}; use crate::GLOBALS; use log::debug; @@ -256,8 +255,9 @@ impl MetaItem { } } -impl AttrItem { - crate fn meta(&self, span: Span) -> Option { +impl Attribute { + /// Extracts the `MetaItem` from inside this `Attribute`. + pub fn meta(&self) -> Option { let mut tokens = self.tokens.trees().peekable(); Some(MetaItem { path: self.path.clone(), @@ -269,18 +269,11 @@ impl AttrItem { } else { return None; }, - span, + span: self.span, }) } -} - -impl Attribute { - /// Extracts the MetaItem from inside this Attribute. - pub fn meta(&self) -> Option { - self.item.meta(self.span) - } - crate fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T> + pub fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T> where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, { let mut parser = Parser::new( @@ -298,11 +291,24 @@ impl Attribute { Ok(result) } - pub fn parse_derive_paths<'a>(&self, sess: &'a ParseSess) -> PResult<'a, Vec> { + pub fn parse_list<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, Vec> + where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, + { if self.tokens.is_empty() { return Ok(Vec::new()); } - self.parse(sess, |p| p.parse_derive_paths()) + self.parse(sess, |parser| { + parser.expect(&token::OpenDelim(token::Paren))?; + let mut list = Vec::new(); + while !parser.eat(&token::CloseDelim(token::Paren)) { + list.push(f(parser)?); + if !parser.eat(&token::Comma) { + parser.expect(&token::CloseDelim(token::Paren))?; + break + } + } + Ok(list) + }) } pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { @@ -312,6 +318,32 @@ impl Attribute { span: self.span, }) } + + /// 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, + { + if self.is_sugared_doc { + let comment = self.value_str().unwrap(); + let meta = mk_name_value_item_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, + path: meta.path, + tokens: meta.kind.tokens(meta.span), + is_sugared_doc: true, + span: self.span, + }) + } else { + f(self) + } + } } /* Constructors */ @@ -352,9 +384,10 @@ crate fn mk_attr_id() -> AttrId { pub fn mk_attr(style: AttrStyle, path: Path, tokens: TokenStream, span: Span) -> Attribute { Attribute { - item: AttrItem { path, tokens }, id: mk_attr_id(), style, + path, + tokens, is_sugared_doc: false, span, } @@ -375,12 +408,10 @@ pub fn mk_sugared_doc_attr(text: Symbol, span: Span) -> Attribute { let lit_kind = LitKind::Str(text, ast::StrStyle::Cooked); let lit = Lit::from_lit_kind(lit_kind, span); Attribute { - item: AttrItem { - path: Path::from_ident(Ident::with_dummy_span(sym::doc).with_span_pos(span)), - tokens: MetaItemKind::NameValue(lit).tokens(span), - }, id: mk_attr_id(), style, + 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, } @@ -438,7 +469,7 @@ pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: Symbol) -> Option } impl MetaItem { - fn token_trees_and_joints(&self) -> Vec { + fn tokens(&self) -> TokenStream { let mut idents = vec![]; let mut last_pos = BytePos(0 as u32); for (i, segment) in self.path.segments.iter().enumerate() { @@ -452,8 +483,8 @@ impl MetaItem { idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into()); last_pos = segment.ident.span.hi(); } - idents.extend(self.kind.token_trees_and_joints(self.span)); - idents + self.kind.tokens(self.span).append_to_tree_and_joint_vec(&mut idents); + TokenStream::new(idents) } fn from_tokens(tokens: &mut iter::Peekable) -> Option @@ -493,7 +524,7 @@ impl MetaItem { } Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt { token::Nonterminal::NtIdent(ident, _) => Path::from_ident(ident), - token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span), + token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()), token::Nonterminal::NtPath(ref path) => path.clone(), _ => return None, }, @@ -512,14 +543,13 @@ impl MetaItem { } impl MetaItemKind { - pub fn token_trees_and_joints(&self, span: Span) -> Vec { + pub fn tokens(&self, span: Span) -> TokenStream { match *self { - MetaItemKind::Word => vec![], + MetaItemKind::Word => TokenStream::empty(), MetaItemKind::NameValue(ref lit) => { - vec![ - TokenTree::token(token::Eq, span).into(), - lit.token_tree().into(), - ] + let mut vec = vec![TokenTree::token(token::Eq, span).into()]; + lit.tokens().append_to_tree_and_joint_vec(&mut vec); + TokenStream::new(vec) } MetaItemKind::List(ref list) => { let mut tokens = Vec::new(); @@ -527,26 +557,17 @@ impl MetaItemKind { if i > 0 { tokens.push(TokenTree::token(token::Comma, span).into()); } - tokens.extend(item.token_trees_and_joints()) + item.tokens().append_to_tree_and_joint_vec(&mut tokens); } - vec![ - TokenTree::Delimited( - DelimSpan::from_single(span), - token::Paren, - TokenStream::new(tokens).into(), - ).into() - ] + TokenTree::Delimited( + DelimSpan::from_single(span), + token::Paren, + TokenStream::new(tokens).into(), + ).into() } } } - // Premature conversions of `TokenTree`s to `TokenStream`s can hurt - // performance. Do not use this function if `token_trees_and_joints()` can - // be used instead. - pub fn tokens(&self, span: Span) -> TokenStream { - TokenStream::new(self.token_trees_and_joints(span)) - } - fn from_tokens(tokens: &mut iter::Peekable) -> Option where I: Iterator, { @@ -588,10 +609,10 @@ impl NestedMetaItem { } } - fn token_trees_and_joints(&self) -> Vec { + fn tokens(&self) -> TokenStream { match *self { - NestedMetaItem::MetaItem(ref item) => item.token_trees_and_joints(), - NestedMetaItem::Literal(ref lit) => vec![lit.token_tree().into()], + NestedMetaItem::MetaItem(ref item) => item.tokens(), + NestedMetaItem::Literal(ref lit) => lit.tokens(), } } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 54dc95291d67f..990358c674ff7 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -10,8 +10,8 @@ use crate::attr; use crate::ast; use crate::edition::Edition; use crate::mut_visit::*; +use crate::parse::{token, ParseSess}; use crate::ptr::P; -use crate::sess::ParseSess; use crate::symbol::sym; use crate::util::map_in_place::MapInPlace; @@ -56,7 +56,6 @@ pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition, (krate, features) } -#[macro_export] macro_rules! configure { ($this:ident, $node:ident) => { match $this.configure($node) { @@ -112,7 +111,25 @@ impl<'a> StripUnconfigured<'a> { return vec![]; } - let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |p| p.parse_cfg_attr()) { + let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |parser| { + parser.expect(&token::OpenDelim(token::Paren))?; + + let cfg_predicate = parser.parse_meta_item()?; + parser.expect(&token::Comma)?; + + // Presumably, the majority of the time there will only be one attr. + let mut expanded_attrs = Vec::with_capacity(1); + + while !parser.check(&token::CloseDelim(token::Paren)) { + let lo = parser.token.span.lo(); + let (path, tokens) = parser.parse_meta_item_unrestricted()?; + expanded_attrs.push((path, tokens, parser.prev_span.with_lo(lo))); + parser.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?; + } + + parser.expect(&token::CloseDelim(token::Paren))?; + Ok((cfg_predicate, expanded_attrs)) + }) { Ok(result) => result, Err(mut e) => { e.emit(); @@ -133,10 +150,11 @@ impl<'a> StripUnconfigured<'a> { // `cfg_attr` inside of another `cfg_attr`. E.g. // `#[cfg_attr(false, cfg_attr(true, some_attr))]`. expanded_attrs.into_iter() - .flat_map(|(item, span)| self.process_cfg_attr(ast::Attribute { - item, + .flat_map(|(path, tokens, span)| self.process_cfg_attr(ast::Attribute { id: attr::mk_attr_id(), style: attr.style, + path, + tokens, is_sugared_doc: false, span, })) diff --git a/src/libsyntax/early_buffered_lints.rs b/src/libsyntax/early_buffered_lints.rs index 5cc953b906628..36c1da2929975 100644 --- a/src/libsyntax/early_buffered_lints.rs +++ b/src/libsyntax/early_buffered_lints.rs @@ -11,7 +11,6 @@ use syntax_pos::MultiSpan; pub enum BufferedEarlyLintId { IllFormedAttributeInput, MetaVariableMisuse, - IncompleteInclude, } /// Stores buffered lint info which can later be passed to `librustc`. diff --git a/src/libsyntax/error_codes.rs b/src/libsyntax/error_codes.rs index 17ea476752064..9925dd8ada0d5 100644 --- a/src/libsyntax/error_codes.rs +++ b/src/libsyntax/error_codes.rs @@ -144,44 +144,6 @@ fn deprecated_function() {} ``` "##, -E0550: r##" -More than one `deprecated` attribute has been put on an item. - -Erroneous code example: - -```compile_fail,E0550 -#[deprecated(note = "because why not?")] -#[deprecated(note = "right?")] // error! -fn the_banished() {} -``` - -The `deprecated` attribute can only be present **once** on an item. - -``` -#[deprecated(note = "because why not, right?")] -fn the_banished() {} // ok! -``` -"##, - -E0551: r##" -An invalid meta-item was used inside an attribute. - -Erroneous code example: - -```compile_fail,E0551 -#[deprecated(note)] // error! -fn i_am_deprecated() {} -``` - -Meta items are the key-value pairs inside of an attribute. To fix this issue, -you need to give a value to the `note` key. Example: - -``` -#[deprecated(note = "because")] // ok! -fn i_am_deprecated() {} -``` -"##, - E0552: r##" A unrecognized representation attribute was used. @@ -227,25 +189,6 @@ If you need the feature, make sure to use a nightly release of the compiler (but be warned that the feature may be removed or altered in the future). "##, -E0556: r##" -The `feature` attribute was badly formed. - -Erroneous code example: - -```compile_fail,E0556 -#![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] // error! -#![feature] // error! -#![feature = "foo"] // error! -``` - -The `feature` attribute only accept a "feature flag" and can only be used on -nightly. Example: - -```ignore (only works in nightly) -#![feature(flag)] -``` -"##, - E0557: r##" A feature attribute named a feature that has been removed. @@ -295,33 +238,6 @@ named `file_that_doesnt_exist.rs` or `file_that_doesnt_exist/mod.rs` in the same directory. "##, -E0584: r##" -A doc comment that is not attached to anything has been encountered. - -Erroneous code example: - -```compile_fail,E0584 -trait Island { - fn lost(); - - /// I'm lost! -} -``` - -A little reminder: a doc comment has to be placed before the item it's supposed -to document. So if you want to document the `Island` trait, you need to put a -doc comment before it, not inside it. Same goes for the `lost` method: the doc -comment needs to be before it: - -``` -/// I'm THE island! -trait Island { - /// I'm lost! - fn lost(); -} -``` -"##, - E0585: r##" A documentation comment that doesn't document anything was found. @@ -519,8 +435,12 @@ features in the `-Z allow_features` flag. // 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 // E0555, // replaced with a generic attribute input check + E0556, // malformed feature, expected just one word + E0584, // file for module `..` found at both .. and .. E0629, // missing 'feature' (rustc_const_unstable) // rustc_const_unstable attribute must be paired with stable/unstable // attribute diff --git a/src/libsyntax_expand/allocator.rs b/src/libsyntax/ext/allocator.rs similarity index 96% rename from src/libsyntax_expand/allocator.rs rename to src/libsyntax/ext/allocator.rs index 3526be17721a8..99aeb5414c5d8 100644 --- a/src/libsyntax_expand/allocator.rs +++ b/src/libsyntax/ext/allocator.rs @@ -1,5 +1,5 @@ -use syntax::{ast, attr, visit}; -use syntax::symbol::{sym, Symbol}; +use crate::{ast, attr, visit}; +use crate::symbol::{sym, Symbol}; use syntax_pos::Span; #[derive(Clone, Copy)] diff --git a/src/libsyntax_expand/base.rs b/src/libsyntax/ext/base.rs similarity index 96% rename from src/libsyntax_expand/base.rs rename to src/libsyntax/ext/base.rs index 58edf23a5b1e2..54cfb80573e5c 100644 --- a/src/libsyntax_expand/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1,19 +1,17 @@ -use crate::expand::{self, AstFragment, Invocation}; -use crate::hygiene::ExpnId; - -use syntax::ast::{self, NodeId, Attribute, Name, PatKind}; -use syntax::attr::{self, HasAttrs, Stability, Deprecation}; -use syntax::source_map::SourceMap; -use syntax::edition::Edition; -use syntax::mut_visit::{self, MutVisitor}; -use syntax::parse::{self, parser, DirectoryOwnership}; -use syntax::parse::token; -use syntax::ptr::P; -use syntax::sess::ParseSess; -use syntax::symbol::{kw, sym, Ident, Symbol}; -use syntax::{ThinVec, MACRO_ARGUMENTS}; -use syntax::tokenstream::{self, TokenStream}; -use syntax::visit::Visitor; +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; +use crate::mut_visit::{self, MutVisitor}; +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}; +use crate::visit::Visitor; use errors::{DiagnosticBuilder, DiagnosticId}; use smallvec::{smallvec, SmallVec}; @@ -851,7 +849,8 @@ pub trait Resolver { 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); + fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment, + extra_placeholders: &[NodeId]); fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension); fn expansion_for_ast_pass( @@ -893,7 +892,7 @@ pub struct ExpansionData { /// when a macro expansion occurs, the resulting nodes have the `backtrace() /// -> expn_data` of their expansion context stored into their span. pub struct ExtCtxt<'a> { - pub parse_sess: &'a ParseSess, + pub parse_sess: &'a parse::ParseSess, pub ecfg: expand::ExpansionConfig<'a>, pub root_path: PathBuf, pub resolver: &'a mut dyn Resolver, @@ -902,7 +901,7 @@ pub struct ExtCtxt<'a> { } impl<'a> ExtCtxt<'a> { - pub fn new(parse_sess: &'a ParseSess, + pub fn new(parse_sess: &'a parse::ParseSess, ecfg: expand::ExpansionConfig<'a>, resolver: &'a mut dyn Resolver) -> ExtCtxt<'a> { @@ -936,7 +935,7 @@ impl<'a> ExtCtxt<'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 ParseSess { self.parse_sess } + 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 { self.current_expansion.id.expn_data().call_site @@ -954,12 +953,6 @@ impl<'a> ExtCtxt<'a> { span.with_call_site_ctxt(self.current_expansion.id) } - /// Equivalent of `Span::mixed_site` from the proc macro API, - /// except that the location is taken from the span passed as an argument. - pub fn with_mixed_site_ctxt(&self, span: Span) -> Span { - span.with_mixed_site_ctxt(self.current_expansion.id) - } - /// Returns span for the macro which originally caused the current expansion to happen. /// /// Stops backtracing at include! boundary. @@ -1072,11 +1065,7 @@ impl<'a> ExtCtxt<'a> { /// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths. /// /// Returns an absolute path to the file that `path` refers to. - pub fn resolve_path( - &self, - path: impl Into, - span: Span, - ) -> Result> { + pub fn resolve_path(&self, path: impl Into, span: Span) -> PathBuf { let path = path.into(); // Relative paths are resolved relative to the file in which they are found @@ -1086,16 +1075,13 @@ impl<'a> ExtCtxt<'a> { let mut result = match self.source_map().span_to_unmapped_path(callsite) { FileName::Real(path) => path, FileName::DocTest(path, _) => path, - other => return Err(self.struct_span_err( - span, - &format!("cannot resolve relative path in non-file source `{}`", other), - )), + other => panic!("cannot resolve relative path in non-file source `{}`", other), }; result.pop(); result.push(path); - Ok(result) + result } else { - Ok(path) + path } } } diff --git a/src/libsyntax_expand/build.rs b/src/libsyntax/ext/build.rs similarity index 98% rename from src/libsyntax_expand/build.rs rename to src/libsyntax/ext/build.rs index 105ffe3ee8a9f..6b93d045588b9 100644 --- a/src/libsyntax_expand/build.rs +++ b/src/libsyntax/ext/build.rs @@ -1,11 +1,10 @@ -use crate::base::ExtCtxt; - -use syntax::ast::{self, Ident, Expr, BlockCheckMode, UnOp, PatKind}; -use syntax::attr; -use syntax::source_map::{respan, Spanned}; -use syntax::ptr::P; -use syntax::symbol::{kw, sym, Symbol}; -use syntax::ThinVec; +use crate::ast::{self, Ident, Expr, BlockCheckMode, UnOp, PatKind}; +use crate::attr; +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 syntax_pos::{Pos, Span}; @@ -563,6 +562,7 @@ impl<'a> ExtCtxt<'a> { P(ast::FnDecl { inputs, output, + c_variadic: false }) } diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax/ext/expand.rs similarity index 87% rename from src/libsyntax_expand/expand.rs rename to src/libsyntax/ext/expand.rs index fc521e5edc06b..02e7c6775a49d 100644 --- a/src/libsyntax_expand/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1,31 +1,29 @@ -use crate::base::*; -use crate::proc_macro::{collect_derives, MarkAttrs}; -use crate::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind}; -use crate::mbe::macro_rules::annotate_err_with_kind; -use crate::placeholders::{placeholder, PlaceholderExpander}; - -use syntax::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path}; -use syntax::ast::{MacStmtStyle, StmtKind, ItemKind}; -use syntax::attr::{self, HasAttrs}; -use syntax::source_map::respan; -use syntax::configure; -use syntax::config::StripUnconfigured; -use syntax::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; -use syntax::mut_visit::*; -use syntax::parse::{DirectoryOwnership, PResult}; -use syntax::parse::token; -use syntax::parse::parser::Parser; -use syntax::print::pprust; -use syntax::ptr::P; -use syntax::symbol::{sym, Symbol}; -use syntax::tokenstream::{TokenStream, TokenTree}; -use syntax::visit::Visitor; -use syntax::util::map_in_place::MapInPlace; +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::respan; +use crate::config::StripUnconfigured; +use crate::ext::base::*; +use crate::ext::proc_macro::{collect_derives, MarkAttrs}; +use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind}; +use crate::ext::mbe::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}; +use crate::mut_visit::*; +use crate::parse::{DirectoryOwnership, PResult, ParseSess}; +use crate::parse::token; +use crate::parse::parser::Parser; +use crate::ptr::P; +use crate::symbol::{sym, Symbol}; +use crate::tokenstream::{TokenStream, TokenTree}; +use crate::visit::{self, Visitor}; +use crate::util::map_in_place::MapInPlace; use errors::{Applicability, FatalError}; use smallvec::{smallvec, SmallVec}; use syntax_pos::{Span, DUMMY_SP, FileName}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use std::io::ErrorKind; use std::{iter, mem, slice}; @@ -74,22 +72,6 @@ macro_rules! ast_fragments { } impl AstFragment { - pub fn add_placeholders(&mut self, placeholders: &[NodeId]) { - if placeholders.is_empty() { - return; - } - match self { - $($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| { - // We are repeating through arguments with `many`, to do that we have to - // mention some macro variable from those arguments even if it's not used. - #[cfg_attr(bootstrap, allow(unused_macros))] - macro _repeating($flat_map_ast_elt) {} - placeholder(AstFragmentKind::$Kind, *id).$make_ast() - })),)?)* - _ => panic!("unexpected AST fragment kind") - } - } - pub fn make_opt_expr(self) -> Option> { match self { AstFragment::OptExpr(expr) => expr, @@ -133,8 +115,8 @@ macro_rules! ast_fragments { } } - impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> { - $(fn $make_ast(self: Box>) + impl<'a> MacResult for crate::ext::mbe::macro_rules::ParserAnyMacro<'a> { + $(fn $make_ast(self: Box>) -> Option<$AstTy> { Some(self.make(AstFragmentKind::$Kind).$make_ast()) })* @@ -357,6 +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 all_derive_placeholders: FxHashMap> = FxHashMap::default(); let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { @@ -405,8 +388,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { "`derive` may only be applied to structs, enums and unions"); if let ast::AttrStyle::Inner = attr.style { let trait_list = derives.iter() - .map(|t| pprust::path_to_string(t)) - .collect::>(); + .map(|t| t.to_string()).collect::>(); let suggestion = format!("#[derive({})]", trait_list.join(", ")); err.span_suggestion( span, "try an outer attribute", suggestion, @@ -434,7 +416,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.resolver.add_derives(invoc.expansion_data.id, SpecialDerives::COPY); } - let mut derive_placeholders = Vec::with_capacity(derives.len()); + 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); @@ -450,7 +434,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } let fragment = invoc.fragment_kind .expect_from_annotatables(::std::iter::once(item)); - self.collect_invocations(fragment, &derive_placeholders) + self.collect_invocations(fragment, derive_placeholders) } }; @@ -469,8 +453,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); while let Some(expanded_fragments) = expanded_fragments.pop() { 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); + expanded_fragment, derive_placeholders); } } fragment_with_placeholders.mut_visit_with(&mut placeholder_expander); @@ -503,14 +489,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { monotonic: self.monotonic, }; fragment.mut_visit_with(&mut collector); - fragment.add_placeholders(extra_placeholders); 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 - ); + self.cx.current_expansion.id, &fragment, extra_placeholders); } (fragment, invocations) @@ -570,6 +555,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment { + let (fragment_kind, span) = (invoc.fragment_kind, invoc.span()); + if fragment_kind == AstFragmentKind::ForeignItems && !self.cx.ecfg.macros_in_extern() { + if let SyntaxExtensionKind::NonMacroAttr { .. } = ext {} else { + emit_feature_err(&self.cx.parse_sess, sym::macros_in_extern, + span, GateIssue::Language, + "macro invocations in `extern {}` blocks are experimental"); + } + } + if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { let expn_data = self.cx.current_expansion.id.expn_data(); let suggested_limit = self.cx.ecfg.recursion_limit * 2; @@ -584,13 +578,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> { FatalError.raise(); } - let (fragment_kind, span) = (invoc.fragment_kind, invoc.span()); match invoc.kind { 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.stream()); - self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span) + let result = + 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; @@ -599,11 +595,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { 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 = pprust::path_to_string(&mac.path), - ); + let msg = format!("non-{kind} macro in {kind} position: {path}", + kind = fragment_kind.name(), path = mac.path); self.cx.span_err(span, &msg); self.cx.trace_macros_diag(); fragment_kind.dummy(span) @@ -632,9 +625,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { | Annotatable::Variant(..) => panic!("unexpected annotatable"), })), DUMMY_SP).into(); - let input = self.extract_proc_macro_attr_input(attr.item.tokens, span); + let input = self.extract_proc_macro_attr_input(attr.tokens, span); let tok_result = expander.expand(self.cx, span, input, item_tok); - self.parse_ast_fragment(tok_result, fragment_kind, &attr.item.path, span) + let res = self.parse_ast_fragment(tok_result, fragment_kind, &attr.path, span); + self.gate_proc_macro_expansion(span, &res); + res } SyntaxExtensionKind::LegacyAttr(expander) => { match attr.parse_meta(self.cx.parse_sess) { @@ -683,12 +678,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } Some(TokenTree::Token(..)) => {} - None => return TokenStream::default(), + None => return TokenStream::empty(), } self.cx.span_err(span, "custom attribute invocations must be \ of the form `#[foo]` or `#[foo(..)]`, the macro name must only be \ followed by a delimiter token"); - TokenStream::default() + TokenStream::empty() } fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) { @@ -725,16 +720,51 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ); } + fn gate_proc_macro_expansion(&self, span: Span, fragment: &AstFragment) { + if self.cx.ecfg.proc_macro_hygiene() { + return + } + + fragment.visit_with(&mut DisallowMacros { + span, + parse_sess: self.cx.parse_sess, + }); + + struct DisallowMacros<'a> { + span: Span, + parse_sess: &'a ParseSess, + } + + impl<'ast, 'a> Visitor<'ast> for DisallowMacros<'a> { + fn visit_item(&mut self, i: &'ast ast::Item) { + if let ast::ItemKind::MacroDef(_) = i.kind { + emit_feature_err( + self.parse_sess, + sym::proc_macro_hygiene, + self.span, + GateIssue::Language, + "procedural macros cannot expand to macro definitions", + ); + } + visit::walk_item(self, i); + } + + fn visit_mac(&mut self, _mac: &'ast ast::Mac) { + // ... + } + } + } + fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) { let kind = match kind { - AstFragmentKind::Expr | + AstFragmentKind::Expr => "expressions", AstFragmentKind::OptExpr => "expressions", AstFragmentKind::Pat => "patterns", + AstFragmentKind::Ty => "types", AstFragmentKind::Stmts => "statements", - AstFragmentKind::Ty | - AstFragmentKind::Items | - AstFragmentKind::TraitItems | - AstFragmentKind::ImplItems | + AstFragmentKind::Items => return, + AstFragmentKind::TraitItems => return, + AstFragmentKind::ImplItems => return, AstFragmentKind::ForeignItems => return, AstFragmentKind::Arms | AstFragmentKind::Fields @@ -765,9 +795,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { span: Span, ) -> AstFragment { let mut parser = self.cx.new_parser_from_tts(toks); - match parse_ast_fragment(&mut parser, kind, false) { + match parser.parse_ast_fragment(kind, false) { Ok(fragment) => { - ensure_complete_parse(&mut parser, path, kind.name(), span); + parser.ensure_complete_parse(path, kind.name(), span); fragment } Err(mut err) => { @@ -781,106 +811,100 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } -pub fn parse_ast_fragment<'a>( - this: &mut Parser<'a>, - kind: AstFragmentKind, - macro_legacy_warnings: bool, -) -> PResult<'a, AstFragment> { - Ok(match kind { - AstFragmentKind::Items => { - let mut items = SmallVec::new(); - while let Some(item) = this.parse_item()? { - items.push(item); - } - AstFragment::Items(items) - } - AstFragmentKind::TraitItems => { - let mut items = SmallVec::new(); - while this.token != token::Eof { - items.push(this.parse_trait_item(&mut false)?); +impl<'a> Parser<'a> { + pub fn parse_ast_fragment(&mut self, kind: AstFragmentKind, macro_legacy_warnings: bool) + -> PResult<'a, AstFragment> { + Ok(match kind { + AstFragmentKind::Items => { + let mut items = SmallVec::new(); + while let Some(item) = self.parse_item()? { + items.push(item); + } + AstFragment::Items(items) } - AstFragment::TraitItems(items) - } - AstFragmentKind::ImplItems => { - let mut items = SmallVec::new(); - while this.token != token::Eof { - items.push(this.parse_impl_item(&mut false)?); + AstFragmentKind::TraitItems => { + let mut items = SmallVec::new(); + while self.token != token::Eof { + items.push(self.parse_trait_item(&mut false)?); + } + AstFragment::TraitItems(items) } - AstFragment::ImplItems(items) - } - AstFragmentKind::ForeignItems => { - let mut items = SmallVec::new(); - while this.token != token::Eof { - items.push(this.parse_foreign_item(DUMMY_SP)?); + AstFragmentKind::ImplItems => { + let mut items = SmallVec::new(); + while self.token != token::Eof { + items.push(self.parse_impl_item(&mut false)?); + } + AstFragment::ImplItems(items) } - AstFragment::ForeignItems(items) - } - AstFragmentKind::Stmts => { - let mut stmts = SmallVec::new(); - while this.token != token::Eof && - // won't make progress on a `}` - this.token != token::CloseDelim(token::Brace) { - if let Some(stmt) = this.parse_full_stmt(macro_legacy_warnings)? { - stmts.push(stmt); + AstFragmentKind::ForeignItems => { + let mut items = SmallVec::new(); + while self.token != token::Eof { + items.push(self.parse_foreign_item(DUMMY_SP)?); } + AstFragment::ForeignItems(items) } - AstFragment::Stmts(stmts) - } - AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?), - AstFragmentKind::OptExpr => { - if this.token != token::Eof { - AstFragment::OptExpr(Some(this.parse_expr()?)) - } else { - AstFragment::OptExpr(None) + AstFragmentKind::Stmts => { + let mut stmts = SmallVec::new(); + while self.token != token::Eof && + // won't make progress on a `}` + self.token != token::CloseDelim(token::Brace) { + if let Some(stmt) = self.parse_full_stmt(macro_legacy_warnings)? { + stmts.push(stmt); + } + } + AstFragment::Stmts(stmts) } - }, - AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?), - AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat(None)?), - AstFragmentKind::Arms - | AstFragmentKind::Fields - | AstFragmentKind::FieldPats - | AstFragmentKind::GenericParams - | AstFragmentKind::Params - | AstFragmentKind::StructFields - | AstFragmentKind::Variants - => panic!("unexpected AST fragment kind"), - }) -} + AstFragmentKind::Expr => AstFragment::Expr(self.parse_expr()?), + AstFragmentKind::OptExpr => { + if self.token != token::Eof { + AstFragment::OptExpr(Some(self.parse_expr()?)) + } else { + AstFragment::OptExpr(None) + } + }, + 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"), + }) + } -pub fn ensure_complete_parse<'a>( - this: &mut Parser<'a>, - macro_path: &Path, - kind_name: &str, - span: Span, -) { - if this.token != token::Eof { - let msg = format!("macro expansion ignores token `{}` and any following", - this.this_token_to_string()); - // Avoid emitting backtrace info twice. - let def_site_span = this.token.span.with_ctxt(SyntaxContext::root()); - let mut err = this.struct_span_err(def_site_span, &msg); - err.span_label(span, "caused by the macro expansion here"); - let msg = format!( - "the usage of `{}!` is likely invalid in {} context", - pprust::path_to_string(macro_path), - kind_name, - ); - err.note(&msg); - let semi_span = this.sess.source_map().next_point(span); - - let semi_full_span = semi_span.to(this.sess.source_map().next_point(semi_span)); - match this.sess.source_map().span_to_snippet(semi_full_span) { - Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => { - err.span_suggestion( - semi_span, - "you might be missing a semicolon here", - ";".to_owned(), - Applicability::MaybeIncorrect, - ); + pub fn ensure_complete_parse(&mut self, macro_path: &Path, kind_name: &str, span: Span) { + if self.token != token::Eof { + 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::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!( + "the usage of `{}!` is likely invalid in {} context", + macro_path, + kind_name, + ); + err.note(&msg); + let semi_span = self.sess.source_map().next_point(span); + + let semi_full_span = semi_span.to(self.sess.source_map().next_point(semi_span)); + match self.sess.source_map().span_to_snippet(semi_full_span) { + Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => { + err.span_suggestion( + semi_span, + "you might be missing a semicolon here", + ";".to_owned(), + Applicability::MaybeIncorrect, + ); + } + _ => {} } - _ => {} + err.emit(); } - err.emit(); } } @@ -1418,14 +1442,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { return noop_visit_attribute(at, self); } - let filename = match self.cx.resolve_path(&*file.as_str(), it.span()) { - Ok(filename) => filename, - Err(mut err) => { - err.emit(); - continue; - } - }; - + let filename = self.cx.resolve_path(&*file.as_str(), it.span()); match self.cx.source_map().load_file(&filename) { Ok(source_file) => { let src = source_file.src.as_ref() @@ -1513,10 +1530,11 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items); *at = attr::Attribute { - item: AttrItem { path: meta.path, tokens: meta.kind.tokens(meta.span) }, span: at.span, id: at.id, style: at.style, + path: meta.path, + tokens: meta.kind.tokens(meta.span), is_sugared_doc: false, }; } else { @@ -1560,6 +1578,9 @@ impl<'feat> ExpansionConfig<'feat> { } } + fn macros_in_extern(&self) -> bool { + self.features.map_or(false, |features| features.macros_in_extern) + } fn proc_macro_hygiene(&self) -> bool { self.features.map_or(false, |features| features.proc_macro_hygiene) } diff --git a/src/libsyntax_expand/mbe.rs b/src/libsyntax/ext/mbe.rs similarity index 96% rename from src/libsyntax_expand/mbe.rs rename to src/libsyntax/ext/mbe.rs index d0f790638efa3..a87da791c9b4f 100644 --- a/src/libsyntax_expand/mbe.rs +++ b/src/libsyntax/ext/mbe.rs @@ -9,9 +9,9 @@ crate mod macro_parser; crate mod macro_rules; crate mod quoted; -use syntax::ast; -use syntax::parse::token::{self, Token, TokenKind}; -use syntax::tokenstream::{DelimSpan}; +use crate::ast; +use crate::parse::token::{self, Token, TokenKind}; +use crate::tokenstream::{DelimSpan}; use syntax_pos::{BytePos, Span}; @@ -73,7 +73,7 @@ impl KleeneToken { /// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star) /// for token sequences. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] enum KleeneOp { /// Kleene star (`*`) for zero or more repetitions ZeroOrMore, diff --git a/src/libsyntax_expand/mbe/macro_check.rs b/src/libsyntax/ext/mbe/macro_check.rs similarity index 98% rename from src/libsyntax_expand/mbe/macro_check.rs rename to src/libsyntax/ext/mbe/macro_check.rs index 50abda8d45e97..97074f5cbe46c 100644 --- a/src/libsyntax_expand/mbe/macro_check.rs +++ b/src/libsyntax/ext/mbe/macro_check.rs @@ -104,13 +104,13 @@ //! Kleene operators under which a meta-variable is repeating is the concatenation of the stacks //! stored when entering a macro definition starting from the state in which the meta-variable is //! bound. -use crate::mbe::{KleeneToken, TokenTree}; - -use syntax::ast::NodeId; -use syntax::early_buffered_lints::BufferedEarlyLintId; -use syntax::parse::token::{DelimToken, Token, TokenKind}; -use syntax::sess::ParseSess; -use syntax::symbol::{kw, sym}; +use crate::ast::NodeId; +use crate::early_buffered_lints::BufferedEarlyLintId; +use crate::ext::mbe::{KleeneToken, TokenTree}; +use crate::parse::token::TokenKind; +use crate::parse::token::{DelimToken, Token}; +use crate::parse::ParseSess; +use crate::symbol::{kw, sym}; use rustc_data_structures::fx::FxHashMap; use smallvec::SmallVec; diff --git a/src/libsyntax_expand/mbe/macro_parser.rs b/src/libsyntax/ext/mbe/macro_parser.rs similarity index 95% rename from src/libsyntax_expand/mbe/macro_parser.rs rename to src/libsyntax/ext/mbe/macro_parser.rs index 3efe22626a9fa..8f49ba9572d77 100644 --- a/src/libsyntax_expand/mbe/macro_parser.rs +++ b/src/libsyntax/ext/mbe/macro_parser.rs @@ -74,16 +74,14 @@ crate use NamedMatch::*; crate use ParseResult::*; use TokenTreeOrTokenTreeSlice::*; -use crate::mbe::{self, TokenTree}; - -use syntax::ast::{Ident, Name}; -use syntax::parse::{Directory, PResult}; -use syntax::parse::parser::{Parser, PathStyle}; -use syntax::parse::token::{self, DocComment, Nonterminal, Token}; -use syntax::print::pprust; -use syntax::sess::ParseSess; -use syntax::symbol::{kw, sym, Symbol}; -use syntax::tokenstream::{DelimSpan, TokenStream}; +use crate::ast::{Ident, Name}; +use crate::ext::mbe::{self, TokenTree}; +use crate::parse::{Directory, ParseSess}; +use crate::parse::parser::{Parser, PathStyle}; +use crate::parse::token::{self, DocComment, Nonterminal, Token}; +use crate::print::pprust; +use crate::symbol::{kw, sym, Symbol}; +use crate::tokenstream::{DelimSpan, TokenStream}; use errors::FatalError; use smallvec::{smallvec, SmallVec}; @@ -652,7 +650,7 @@ pub(super) fn parse( directory, recurse_into_modules, true, - syntax::MACRO_ARGUMENTS, + crate::MACRO_ARGUMENTS, ); // A queue of possible matcher positions. We initialize it with the matcher position in which @@ -890,38 +888,31 @@ fn may_begin_with(token: &Token, name: Name) -> bool { /// /// The parsed non-terminal. fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal { - // FIXME(Centril): Consider moving this to `parser.rs` to make - // the visibilities of the methods used below `pub(super)` at most. - if name == sym::tt { return token::NtTT(p.parse_token_tree()); } // check at the beginning and the parser checks after each bump p.process_potential_macro_variable(); - match parse_nt_inner(p, sp, name) { - Ok(nt) => nt, - Err(mut err) => { - err.emit(); - FatalError.raise(); - } - } -} - -fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, Nonterminal> { - Ok(match name { - sym::item => match p.parse_item()? { + match name { + sym::item => match panictry!(p.parse_item()) { Some(i) => token::NtItem(i), - None => return Err(p.fatal("expected an item keyword")), + None => { + p.fatal("expected an item keyword").emit(); + FatalError.raise(); + } }, - sym::block => token::NtBlock(p.parse_block()?), - sym::stmt => match p.parse_stmt()? { + sym::block => token::NtBlock(panictry!(p.parse_block())), + sym::stmt => match panictry!(p.parse_stmt()) { Some(s) => token::NtStmt(s), - None => return Err(p.fatal("expected a statement")), + None => { + p.fatal("expected a statement").emit(); + FatalError.raise(); + } }, - sym::pat => token::NtPat(p.parse_pat(None)?), - sym::expr => token::NtExpr(p.parse_expr()?), - sym::literal => token::NtLiteral(p.parse_literal_maybe_minus()?), - sym::ty => token::NtTy(p.parse_ty()?), + sym::pat => token::NtPat(panictry!(p.parse_pat(None))), + sym::expr => token::NtExpr(panictry!(p.parse_expr())), + sym::literal => token::NtLiteral(panictry!(p.parse_literal_maybe_minus())), + sym::ty => token::NtTy(panictry!(p.parse_ty())), // this could be handled like a token, since it is one sym::ident => if let Some((name, is_raw)) = get_macro_name(&p.token) { let span = p.token.span; @@ -929,19 +920,21 @@ fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, token::NtIdent(Ident::new(name, span), is_raw) } else { let token_str = pprust::token_to_string(&p.token); - return Err(p.fatal(&format!("expected ident, found {}", &token_str))); + p.fatal(&format!("expected ident, found {}", &token_str)).emit(); + FatalError.raise() } - sym::path => token::NtPath(p.parse_path(PathStyle::Type)?), - sym::meta => token::NtMeta(p.parse_attr_item()?), - sym::vis => token::NtVis(p.parse_visibility(true)?), + sym::path => token::NtPath(panictry!(p.parse_path(PathStyle::Type))), + sym::meta => token::NtMeta(panictry!(p.parse_meta_item())), + sym::vis => token::NtVis(panictry!(p.parse_visibility(true))), sym::lifetime => if p.check_lifetime() { token::NtLifetime(p.expect_lifetime().ident) } else { let token_str = pprust::token_to_string(&p.token); - return Err(p.fatal(&format!("expected a lifetime, found `{}`", &token_str))); + p.fatal(&format!("expected a lifetime, found `{}`", &token_str)).emit(); + FatalError.raise(); } // this is not supposed to happen, since it has been checked // when compiling the macro. _ => p.span_bug(sp, "invalid fragment specifier"), - }) + } } diff --git a/src/libsyntax_expand/mbe/macro_rules.rs b/src/libsyntax/ext/mbe/macro_rules.rs similarity index 95% rename from src/libsyntax_expand/mbe/macro_rules.rs rename to src/libsyntax/ext/mbe/macro_rules.rs index 9a4130b2d8d02..aec4a68314120 100644 --- a/src/libsyntax_expand/mbe/macro_rules.rs +++ b/src/libsyntax/ext/mbe/macro_rules.rs @@ -1,25 +1,23 @@ -use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; -use crate::base::{SyntaxExtension, SyntaxExtensionKind}; -use crate::expand::{AstFragment, AstFragmentKind, ensure_complete_parse, parse_ast_fragment}; -use crate::mbe; -use crate::mbe::macro_check; -use crate::mbe::macro_parser::parse; -use crate::mbe::macro_parser::{Error, Failure, Success}; -use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedParseResult}; -use crate::mbe::transcribe::transcribe; - -use syntax::ast; -use syntax::attr::{self, TransparencyError}; -use syntax::edition::Edition; -use syntax::feature_gate::Features; -use syntax::parse::parser::Parser; -use syntax::parse::token::TokenKind::*; -use syntax::parse::token::{self, NtTT, Token}; -use syntax::parse::Directory; -use syntax::print::pprust; -use syntax::sess::ParseSess; -use syntax::symbol::{kw, sym, Symbol}; -use syntax::tokenstream::{DelimSpan, TokenStream}; +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}; +use crate::ext::expand::{AstFragment, AstFragmentKind}; +use crate::ext::mbe; +use crate::ext::mbe::macro_check; +use crate::ext::mbe::macro_parser::parse; +use crate::ext::mbe::macro_parser::{Error, Failure, Success}; +use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedParseResult}; +use crate::ext::mbe::transcribe::transcribe; +use crate::feature_gate::Features; +use crate::parse::parser::Parser; +use crate::parse::token::TokenKind::*; +use crate::parse::token::{self, NtTT, Token}; +use crate::parse::{Directory, ParseSess}; +use crate::print::pprust; +use crate::symbol::{kw, sym, Symbol}; +use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; use errors::{DiagnosticBuilder, FatalError}; use log::debug; @@ -67,7 +65,7 @@ crate fn annotate_err_with_kind( impl<'a> ParserAnyMacro<'a> { crate fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; - let fragment = panictry!(parse_ast_fragment(parser, kind, true).map_err(|mut e| { + let fragment = panictry!(parser.parse_ast_fragment(kind, true).map_err(|mut e| { if parser.token == token::Eof && e.message().ends_with(", found ``") { if !e.span.is_dummy() { // early end of macro arm (#52866) @@ -129,7 +127,7 @@ impl<'a> ParserAnyMacro<'a> { // Make sure we don't have any tokens left to parse so we don't silently drop anything. let path = ast::Path::from_ident(macro_ident.with_span_pos(site_span)); - ensure_complete_parse(parser, &path, kind.name(), site_span); + parser.ensure_complete_parse(&path, kind.name(), site_span); fragment } } @@ -176,8 +174,7 @@ fn generic_extension<'cx>( rhses: &[mbe::TokenTree], ) -> Box { if cx.trace_macros() { - let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone())); - trace_macros_note(cx, sp, msg); + trace_macros_note(cx, sp, format!("expanding `{}! {{ {} }}`", name, arg)); } // Which arm's failure should we report? (the one furthest along) @@ -190,7 +187,7 @@ fn generic_extension<'cx>( _ => cx.span_bug(sp, "malformed macro lhs"), }; - match parse_tt(cx, lhs_tt, arg.clone()) { + match TokenTree::parse(cx, lhs_tt, arg.clone()) { Success(named_matches) => { let rhs = match rhses[i] { // ignore delimiters @@ -215,8 +212,7 @@ fn generic_extension<'cx>( } if cx.trace_macros() { - let msg = format!("to `{}`", pprust::tts_to_string(tts.clone())); - trace_macros_note(cx, sp, msg); + trace_macros_note(cx, sp, format!("to `{}`", tts)); } let directory = Directory { @@ -266,7 +262,7 @@ fn generic_extension<'cx>( mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], _ => continue, }; - match parse_tt(cx, lhs_tt, arg.clone()) { + match TokenTree::parse(cx, lhs_tt, arg.clone()) { Success(_) => { if comma_span.is_dummy() { err.note("you might be missing a comma"); @@ -1159,7 +1155,7 @@ fn is_legal_fragment_specifier( fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { match *tt { - mbe::TokenTree::Token(ref token) => pprust::token_to_string(&token), + mbe::TokenTree::Token(ref token) => crate::print::pprust::token_to_string(&token), mbe::TokenTree::MetaVar(_, name) => format!("${}", name), mbe::TokenTree::MetaVarDecl(_, name, kind) => format!("${}:{}", name, kind), _ => panic!( @@ -1169,14 +1165,17 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } } -/// Use this token tree as a matcher to parse given tts. -fn parse_tt(cx: &ExtCtxt<'_>, mtch: &[mbe::TokenTree], tts: TokenStream) -> NamedParseResult { - // `None` is because we're not interpolating - let directory = Directory { - path: Cow::from(cx.current_expansion.module.directory.as_path()), - ownership: cx.current_expansion.directory_ownership, - }; - parse(cx.parse_sess(), tts, mtch, Some(directory), true) +impl TokenTree { + /// Use this token tree as a matcher to parse given tts. + fn parse(cx: &ExtCtxt<'_>, mtch: &[mbe::TokenTree], tts: TokenStream) + -> NamedParseResult { + // `None` is because we're not interpolating + let directory = Directory { + path: Cow::from(cx.current_expansion.module.directory.as_path()), + ownership: cx.current_expansion.directory_ownership, + }; + parse(cx.parse_sess(), tts, mtch, Some(directory), true) + } } /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For diff --git a/src/libsyntax_expand/mbe/quoted.rs b/src/libsyntax/ext/mbe/quoted.rs similarity index 97% rename from src/libsyntax_expand/mbe/quoted.rs rename to src/libsyntax/ext/mbe/quoted.rs index cedd59233adf5..8cb85bdef762f 100644 --- a/src/libsyntax_expand/mbe/quoted.rs +++ b/src/libsyntax/ext/mbe/quoted.rs @@ -1,12 +1,11 @@ -use crate::mbe::macro_parser; -use crate::mbe::{TokenTree, KleeneOp, KleeneToken, SequenceRepetition, Delimited}; - -use syntax::ast; -use syntax::parse::token::{self, Token}; -use syntax::print::pprust; -use syntax::sess::ParseSess; -use syntax::symbol::kw; -use syntax::tokenstream; +use crate::ast; +use crate::ext::mbe::macro_parser; +use crate::ext::mbe::{TokenTree, KleeneOp, KleeneToken, SequenceRepetition, Delimited}; +use crate::parse::token::{self, Token}; +use crate::parse::ParseSess; +use crate::print::pprust; +use crate::symbol::kw; +use crate::tokenstream; use syntax_pos::Span; diff --git a/src/libsyntax_expand/mbe/transcribe.rs b/src/libsyntax/ext/mbe/transcribe.rs similarity index 97% rename from src/libsyntax_expand/mbe/transcribe.rs rename to src/libsyntax/ext/mbe/transcribe.rs index 94523bbf91b5a..ba818ebd35c7f 100644 --- a/src/libsyntax_expand/mbe/transcribe.rs +++ b/src/libsyntax/ext/mbe/transcribe.rs @@ -1,11 +1,10 @@ -use crate::base::ExtCtxt; -use crate::mbe; -use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; - -use syntax::ast::{Ident, Mac}; -use syntax::mut_visit::{self, MutVisitor}; -use syntax::parse::token::{self, NtTT, Token}; -use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; +use crate::ast::{Ident, Mac}; +use crate::ext::base::ExtCtxt; +use crate::ext::mbe; +use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; +use crate::mut_visit::{self, MutVisitor}; +use crate::parse::token::{self, NtTT, Token}; +use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; use smallvec::{smallvec, SmallVec}; @@ -96,7 +95,7 @@ pub(super) fn transcribe( ) -> TokenStream { // Nothing for us to transcribe... if src.is_empty() { - return TokenStream::default(); + return TokenStream::empty(); } // We descend into the RHS (`src`), expanding things as we go. This stack contains the things diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax/ext/placeholders.rs similarity index 92% rename from src/libsyntax_expand/placeholders.rs rename to src/libsyntax/ext/placeholders.rs index e595888dae7d1..8eecef1020d0a 100644 --- a/src/libsyntax_expand/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -1,12 +1,11 @@ -use crate::base::ExtCtxt; -use crate::expand::{AstFragment, AstFragmentKind}; - -use syntax::ast; -use syntax::source_map::{DUMMY_SP, dummy_spanned}; -use syntax::tokenstream::TokenStream; -use syntax::mut_visit::*; -use syntax::ptr::P; -use syntax::ThinVec; +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::tokenstream::TokenStream; +use crate::mut_visit::*; +use crate::ptr::P; +use crate::ThinVec; use smallvec::{smallvec, SmallVec}; @@ -16,7 +15,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { fn mac_placeholder() -> ast::Mac { ast::Mac { path: ast::Path { span: DUMMY_SP, segments: Vec::new() }, - tts: TokenStream::default().into(), + tts: TokenStream::empty().into(), delim: ast::MacDelimiter::Brace, span: DUMMY_SP, prior_type_ascription: None, @@ -33,12 +32,12 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { attrs: ThinVec::new(), kind: ast::ExprKind::Mac(mac_placeholder()), }); - let ty = || P(ast::Ty { + let ty = P(ast::Ty { id, kind: ast::TyKind::Mac(mac_placeholder()), span, }); - let pat = || P(ast::Pat { + let pat = P(ast::Pat { id, kind: ast::PatKind::Mac(mac_placeholder()), span, @@ -84,7 +83,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { body: expr_placeholder(), guard: None, id, - pat: pat(), + pat, span, is_placeholder: true, } @@ -106,7 +105,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { id, ident, is_shorthand: false, - pat: pat(), + pat, span, is_placeholder: true, } @@ -125,9 +124,9 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { ast::Param { attrs: Default::default(), id, - pat: pat(), + pat, span, - ty: ty(), + ty, is_placeholder: true, } ]), @@ -137,7 +136,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { id, ident: None, span, - ty: ty(), + ty, vis, is_placeholder: true, } @@ -171,8 +170,17 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { } } - pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { + 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 placeholder in placeholders { + match self.remove(placeholder) { + AstFragment::Items(derived_items) => items.extend(derived_items), + _ => unreachable!(), + } + } + fragment = AstFragment::Items(items); + } self.expanded_fragments.insert(id, fragment); } diff --git a/src/libsyntax_expand/proc_macro.rs b/src/libsyntax/ext/proc_macro.rs similarity index 86% rename from src/libsyntax_expand/proc_macro.rs rename to src/libsyntax/ext/proc_macro.rs index 07b618c99a556..e17bbf79fd5e0 100644 --- a/src/libsyntax_expand/proc_macro.rs +++ b/src/libsyntax/ext/proc_macro.rs @@ -1,22 +1,23 @@ -use crate::base::{self, *}; -use crate::proc_macro_server; - -use syntax::ast::{self, ItemKind, Attribute, Mac}; -use syntax::attr::{mark_used, mark_known}; -use syntax::errors::{Applicability, FatalError}; -use syntax::parse::{self, token}; -use syntax::symbol::sym; -use syntax::tokenstream::{self, TokenStream}; -use syntax::visit::Visitor; +use crate::ast::{self, ItemKind, Attribute, Mac}; +use crate::attr::{mark_used, mark_known}; +use crate::errors::{Applicability, FatalError}; +use crate::ext::base::{self, *}; +use crate::ext::proc_macro_server; +use crate::parse::{self, token}; +use crate::parse::parser::PathStyle; +use crate::symbol::sym; +use crate::tokenstream::{self, TokenStream}; +use crate::visit::Visitor; use rustc_data_structures::sync::Lrc; use syntax_pos::{Span, DUMMY_SP}; -const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread; +const EXEC_STRATEGY: proc_macro::bridge::server::SameThread = + proc_macro::bridge::server::SameThread; pub struct BangProcMacro { - pub client: pm::bridge::client::Client< - fn(pm::TokenStream) -> pm::TokenStream, + pub client: proc_macro::bridge::client::Client< + fn(proc_macro::TokenStream) -> proc_macro::TokenStream, >, } @@ -44,7 +45,9 @@ impl base::ProcMacro for BangProcMacro { } pub struct AttrProcMacro { - pub client: pm::bridge::client::Client pm::TokenStream>, + pub client: proc_macro::bridge::client::Client< + fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream, + >, } impl base::AttrProcMacro for AttrProcMacro { @@ -72,7 +75,9 @@ impl base::AttrProcMacro for AttrProcMacro { } pub struct ProcMacroDerive { - pub client: pm::bridge::client::Client pm::TokenStream>, + pub client: proc_macro::bridge::client::Client< + fn(proc_macro::TokenStream) -> proc_macro::TokenStream, + >, } impl MultiItemModifier for ProcMacroDerive { @@ -200,7 +205,8 @@ crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec) return false; } - match attr.parse_derive_paths(cx.parse_sess) { + match attr.parse_list(cx.parse_sess, + |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) { Ok(traits) => { result.extend(traits); true diff --git a/src/libsyntax_expand/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs similarity index 96% rename from src/libsyntax_expand/proc_macro_server.rs rename to src/libsyntax/ext/proc_macro_server.rs index 4ce99cfe73b5c..dfec9ee28809a 100644 --- a/src/libsyntax_expand/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -1,19 +1,16 @@ -use crate::base::ExtCtxt; - -use syntax::ast; -use syntax::parse::{self, token}; -use syntax::parse::lexer::comments; -use syntax::print::pprust; -use syntax::sess::ParseSess; -use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint}; +use crate::ast; +use crate::ext::base::ExtCtxt; +use crate::parse::{self, token, ParseSess}; +use crate::parse::lexer::comments; +use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint}; use errors::Diagnostic; use rustc_data_structures::sync::Lrc; use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span}; use syntax_pos::symbol::{kw, sym, Symbol}; -use pm::{Delimiter, Level, LineColumn, Spacing}; -use pm::bridge::{server, TokenTree}; +use proc_macro::{Delimiter, Level, LineColumn, Spacing}; +use proc_macro::bridge::{server, TokenTree}; use std::{ascii, panic}; use std::ops::Bound; @@ -52,7 +49,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec)> { fn from_internal(((tree, is_joint), sess, stack): (TreeAndJoint, &ParseSess, &mut Vec)) -> Self { - use syntax::parse::token::*; + use crate::parse::token::*; let joint = is_joint == Joint; let Token { kind, span } = match tree { @@ -177,7 +174,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec)> } Interpolated(nt) => { - let stream = parse::nt_to_tokenstream(&nt, sess, span); + let stream = nt.to_tokenstream(sess, span); TokenTree::Group(Group { delimiter: Delimiter::None, stream, @@ -193,7 +190,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec)> impl ToInternal for TokenTree { fn to_internal(self) -> TokenStream { - use syntax::parse::token::*; + use crate::parse::token::*; let (ch, joint, span) = match self { TokenTree::Punct(Punct { ch, joint, span }) => (ch, joint, span), @@ -335,7 +332,8 @@ impl Ident { if !Self::is_valid(&string) { panic!("`{:?}` is not a valid identifier", string) } - if is_raw && !sym.can_be_raw() { + // Get rid of gensyms to conservatively check rawness on the string contents only. + if is_raw && !sym.as_interned_str().as_symbol().can_be_raw() { panic!("`{}` cannot be a raw identifier", string); } Ident { sym, is_raw, span } @@ -357,7 +355,6 @@ pub(crate) struct Rustc<'a> { sess: &'a ParseSess, def_site: Span, call_site: Span, - mixed_site: Span, } impl<'a> Rustc<'a> { @@ -367,7 +364,6 @@ impl<'a> Rustc<'a> { sess: cx.parse_sess, def_site: cx.with_def_site_ctxt(expn_data.def_site), call_site: cx.with_call_site_ctxt(expn_data.call_site), - mixed_site: cx.with_mixed_site_ctxt(expn_data.call_site), } } @@ -395,7 +391,7 @@ impl server::Types for Rustc<'_> { impl server::TokenStream for Rustc<'_> { fn new(&mut self) -> Self::TokenStream { - TokenStream::default() + TokenStream::empty() } fn is_empty(&mut self, stream: &Self::TokenStream) -> bool { stream.is_empty() @@ -409,7 +405,7 @@ impl server::TokenStream for Rustc<'_> { ) } fn to_string(&mut self, stream: &Self::TokenStream) -> String { - pprust::tts_to_string(stream.clone()) + stream.to_string() } fn from_token_tree( &mut self, @@ -668,9 +664,6 @@ impl server::Span for Rustc<'_> { fn call_site(&mut self) -> Self::Span { self.call_site } - fn mixed_site(&mut self) -> Self::Span { - self.mixed_site - } fn source_file(&mut self, span: Self::Span) -> Self::SourceFile { self.sess.source_map().lookup_char_pos(span.lo()).file } diff --git a/src/libsyntax/feature_gate/accepted.rs b/src/libsyntax/feature_gate/accepted.rs index 36fcab8450b85..5538daf388e2f 100644 --- a/src/libsyntax/feature_gate/accepted.rs +++ b/src/libsyntax/feature_gate/accepted.rs @@ -245,10 +245,6 @@ declare_features! ( (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), - /// Allows macro invocations in `extern {}` blocks. - (accepted, macros_in_extern, "1.40.0", Some(49476), None), - /// Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008). - (accepted, non_exhaustive, "1.40.0", Some(44109), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index f6e1d6c422499..38c16dbac6ab7 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -330,13 +330,8 @@ declare_features! ( /// Allows exhaustive pattern matching on types that contain uninhabited types. (active, exhaustive_patterns, "1.13.0", Some(51085), None), - /// Allows `union`s to implement `Drop`. Moreover, `union`s may now include fields - /// that don't implement `Copy` as long as they don't have any drop glue. - /// This is checked recursively. On encountering type variable where no progress can be made, - /// `T: Copy` is used as a substitute for "no drop glue". - /// - /// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0. - (active, untagged_unions, "1.13.0", Some(55149), 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), @@ -383,6 +378,9 @@ declare_features! ( /// 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), @@ -404,6 +402,9 @@ declare_features! ( /// 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), @@ -521,21 +522,6 @@ declare_features! ( /// Allows the use of or-patterns (e.g., `0 | 1`). (active, or_patterns, "1.38.0", Some(54883), None), - /// Allows the definition of `const extern fn` and `const unsafe extern fn`. - (active, const_extern_fn, "1.40.0", Some(64926), None), - - /// Allows the use of raw-dylibs (RFC 2627). - (active, raw_dylib, "1.40.0", Some(58713), None), - - /// Allows `#[track_caller]` to be used which provides - /// accurate caller location reporting during panic (RFC 2091). - (active, track_caller, "1.40.0", Some(47809), None), - - /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe. - /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and - /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. - (active, object_safe_for_dispatch, "1.40.0", Some(43561), None), - // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- @@ -550,6 +536,4 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::const_generics, sym::or_patterns, sym::let_chains, - sym::raw_dylib, - sym::track_caller, ]; diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index efe84238795a5..d14afc6deaa69 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -9,8 +9,8 @@ use super::active::Features; use crate::ast; use crate::attr::AttributeTemplate; -use crate::sess::ParseSess; use crate::symbol::{Symbol, sym}; +use crate::parse::ParseSess; use syntax_pos::Span; use rustc_data_structures::fx::FxHashMap; @@ -29,7 +29,6 @@ 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::target_has_atomic_load_store, 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)), ]; @@ -252,7 +251,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(path, Normal, template!(NameValueStr: "file")), ungated!(no_std, CrateLevel, template!(Word)), ungated!(no_implicit_prelude, Normal, template!(Word)), - ungated!(non_exhaustive, Whitelisted, template!(Word)), // Runtime ungated!(windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console")), @@ -278,35 +276,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "the `link_args` attribute is experimental and not portable across platforms, \ it is recommended to use `#[link(name = \"foo\")] instead", ), - gated!( - link_ordinal, Whitelisted, template!(List: "ordinal"), raw_dylib, - experimental!(link_ordinal) - ), // Plugins: - ( - sym::plugin_registrar, Normal, template!(Word), - Gated( - Stability::Deprecated( - "https://github.com/rust-lang/rust/pull/64675", - Some("may be removed in a future compiler version"), - ), - sym::plugin_registrar, - "compiler plugins are deprecated", - cfg_fn!(plugin_registrar) - ) - ), - ( - sym::plugin, CrateLevel, template!(List: "name|name(args)"), - Gated( - Stability::Deprecated( - "https://github.com/rust-lang/rust/pull/64675", - Some("may be removed in a future compiler version"), - ), - sym::plugin, - "compiler plugins are deprecated", - cfg_fn!(plugin) - ) + ungated!(plugin_registrar, Normal, template!(Word)), + gated!( + plugin, CrateLevel, template!(List: "name|name(args)"), + "compiler plugins are experimental and possibly buggy", ), // Testing: @@ -315,6 +290,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ 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!( @@ -329,7 +307,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)), - gated!(track_caller, Whitelisted, template!(Word), experimental!(track_caller)), // ========================================================================== // Internal attributes: Stability, deprecation, and unsafe: diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 502b1c0f74371..622b48ab9281e 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -3,12 +3,16 @@ 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, NodeId, PatKind, VariantData}; +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; -use crate::sess::ParseSess; +use crate::parse::{token, ParseSess}; +use crate::parse::parser::Parser; use crate::symbol::{Symbol, sym}; use crate::tokenstream::TokenTree; @@ -52,7 +56,7 @@ macro_rules! gate_feature { }; } -pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) { +crate fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) { PostExpansionVisitor { parse_sess, features }.visit_attribute(attr) } @@ -153,6 +157,9 @@ fn leveled_feature_err<'a, S: Into>( } +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"; @@ -239,70 +246,6 @@ impl<'a> PostExpansionVisitor<'a> { Abi::System => {} } } - - fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) { - 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.data { - VariantData::Tuple(..) | VariantData::Struct(..) => false, - VariantData::Unit(..) => true, - }) - .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span)) - .collect::>(); - - if !discriminant_spans.is_empty() && has_fields { - let mut err = feature_err( - self.parse_sess, - sym::arbitrary_enum_discriminant, - discriminant_spans.clone(), - crate::feature_gate::GateIssue::Language, - "custom discriminant values are not allowed in enums with tuple or struct variants", - ); - for sp in discriminant_spans { - err.span_label(sp, "disallowed custom discriminant"); - } - for variant in variants.iter() { - match &variant.data { - VariantData::Struct(..) => { - err.span_label( - variant.span, - "struct variant defined here", - ); - } - VariantData::Tuple(..) => { - err.span_label( - variant.span, - "tuple variant defined here", - ); - } - VariantData::Unit(..) => {} - } - } - err.emit(); - } - } - - fn check_gat(&self, generics: &ast::Generics, span: Span) { - if !generics.params.is_empty() { - gate_feature_post!( - &self, - generic_associated_types, - span, - "generic associated types are unstable" - ); - } - if !generics.where_clause.predicates.is_empty() { - gate_feature_post!( - &self, - generic_associated_types, - span, - "where clauses on associated types are unstable" - ); - } - } } impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { @@ -410,7 +353,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { let has_feature = self.features.arbitrary_enum_discriminant; if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) { - self.maybe_report_invalid_custom_discriminants(&variants); + Parser::maybe_report_invalid_custom_discriminants(self.parse_sess, &variants); } } @@ -435,6 +378,20 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "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, @@ -498,6 +455,37 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } + fn visit_expr(&mut self, e: &'a ast::Expr) { + match e.kind { + 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.kind { PatKind::Slice(pats) => { @@ -517,12 +505,25 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } } + 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, _: NodeId) { + 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 @@ -530,20 +531,40 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { self.check_abi(header.abi, span); } - if fn_decl.c_variadic() { + 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.kind { ast::TraitItemKind::Method(ref sig, ref block) => { if block.is_none() { self.check_abi(sig.header.abi, ti.span); } - if sig.decl.c_variadic() { + if sig.decl.c_variadic { gate_feature_post!(&self, c_variadic, ti.span, "C-variadic functions are unstable"); } @@ -558,7 +579,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, associated_type_defaults, ti.span, "associated type defaults are unstable"); } - self.check_gat(&ti.generics, ti.span); + 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"); + } } _ => {} } @@ -573,12 +601,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } match ii.kind { - ast::ImplItemKind::Method(ref sig, _) => { - if sig.decl.c_variadic() { - gate_feature_post!(&self, c_variadic, ii.span, - "C-variadic functions are unstable"); - } - } + ast::ImplItemKind::Method(..) => {} ast::ImplItemKind::OpaqueTy(..) => { gate_feature_post!( &self, @@ -588,12 +611,27 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ); } ast::ImplItemKind::TyAlias(_) => { - self.check_gat(&ii.generics, ii.span); + 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], @@ -726,7 +764,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } if let Some(allowed) = allow_features.as_ref() { - if allowed.iter().find(|&f| f == &name.as_str() as &str).is_none() { + 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); @@ -778,23 +816,6 @@ pub fn check_crate(krate: &ast::Crate, 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"); - gate_all!(const_extern_fn, "`const extern fn` definitions are unstable"); - gate_all!(trait_alias, "trait aliases are experimental"); - gate_all!(associated_type_bounds, "associated type bounds are unstable"); - gate_all!(crate_visibility_modifier, "`crate` visibility modifier is experimental"); - gate_all!(const_generics, "const generics are unstable"); - gate_all!(decl_macro, "`macro` is experimental"); - gate_all!(box_patterns, "box pattern syntax is experimental"); - gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental"); - gate_all!(try_blocks, "`try` blocks are unstable"); - gate_all!(label_break_value, "labels on blocks are unstable"); - gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead"); - - // To avoid noise about type ascription in common syntax errors, - // only emit if it is the *only* error. (Also check it last.) - if parse_sess.span_diagnostic.err_count() == 0 { - gate_all!(type_ascription, "type ascription is experimental"); - } visit::walk_crate(&mut visitor, krate); } @@ -828,19 +849,25 @@ impl UnstableFeatures { pub fn is_nightly_build(&self) -> bool { match *self { UnstableFeatures::Allow | UnstableFeatures::Cheat => true, - UnstableFeatures::Disallow => false, + _ => false, } } } fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, unstable: UnstableFeatures) { - if !unstable.is_nightly_build() { - for attr in krate.attrs.iter().filter(|attr| attr.check_name(sym::feature)) { - span_err!( - span_handler, attr.span, E0554, - "`#![feature]` may not be used on the {} release channel", - option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)") - ); + 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 index ba970618c0e13..ca13ab3620508 100644 --- a/src/libsyntax/feature_gate/mod.rs +++ b/src/libsyntax/feature_gate/mod.rs @@ -58,7 +58,8 @@ pub use builtin_attrs::{ deprecated_attributes, is_builtin_attr, is_builtin_attr_name, }; pub use check::{ - check_crate, check_attribute, get_features, feature_err, emit_feature_err, + 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/json.rs b/src/libsyntax/json.rs index 0b157938375e1..2423e1070fc3e 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::{SubDiagnostic, CodeSuggestion, SourceMapper, SourceMapperDyn}; +use errors::{SubDiagnostic, CodeSuggestion, SourceMapper}; use errors::{DiagnosticId, Applicability}; use errors::emitter::{Emitter, HumanReadableErrorType}; @@ -25,9 +25,6 @@ use std::sync::{Arc, Mutex}; use rustc_serialize::json::{as_json, as_pretty_json}; -#[cfg(test)] -mod tests; - pub struct JsonEmitter { dst: Box, registry: Option, @@ -92,8 +89,8 @@ impl JsonEmitter { } impl Emitter for JsonEmitter { - fn emit_diagnostic(&mut self, diag: &errors::Diagnostic) { - let data = Diagnostic::from_errors_diagnostic(diag, 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 { @@ -116,10 +113,6 @@ impl Emitter for JsonEmitter { } } - fn source_map(&self) -> Option<&Lrc> { - Some(&self.sm) - } - fn should_show_explain(&self) -> bool { match self.json_rendered { HumanReadableErrorType::Short(_) => false, @@ -212,10 +205,10 @@ struct ArtifactNotification<'a> { } impl Diagnostic { - fn from_errors_diagnostic(diag: &errors::Diagnostic, + fn from_errors_diagnostic(db: &errors::Diagnostic, je: &JsonEmitter) -> Diagnostic { - let sugg = diag.suggestions.iter().map(|sugg| { + let sugg = db.suggestions.iter().map(|sugg| { Diagnostic { message: sugg.msg.clone(), code: None, @@ -244,30 +237,30 @@ impl Diagnostic { let output = buf.clone(); 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(diag); + ).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(); Diagnostic { - message: diag.message(), - code: DiagnosticCode::map_opt_string(diag.code.clone(), je), - level: diag.level.to_str(), - spans: DiagnosticSpan::from_multispan(&diag.span, je), - children: diag.children.iter().map(|c| { + message: db.message(), + code: DiagnosticCode::map_opt_string(db.code.clone(), je), + level: db.level.to_str(), + spans: DiagnosticSpan::from_multispan(&db.span, je), + children: db.children.iter().map(|c| { Diagnostic::from_sub_diagnostic(c, je) }).chain(sugg).collect(), rendered: Some(output), } } - fn from_sub_diagnostic(diag: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic { + fn from_sub_diagnostic(db: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic { Diagnostic { - message: diag.message(), + message: db.message(), code: None, - level: diag.level.to_str(), - spans: diag.render_span.as_ref() + level: db.level.to_str(), + spans: db.render_span.as_ref() .map(|sp| DiagnosticSpan::from_multispan(sp, je)) - .unwrap_or_else(|| DiagnosticSpan::from_multispan(&diag.span, je)), + .unwrap_or_else(|| DiagnosticSpan::from_multispan(&db.span, je)), children: vec![], rendered: None, } @@ -339,8 +332,8 @@ impl DiagnosticSpan { DiagnosticSpan { file_name: start.file.name.to_string(), - byte_start: start.file.original_relative_byte_pos(span.lo()).0, - byte_end: start.file.original_relative_byte_pos(span.hi()).0, + byte_start: span.lo().0 - start.file.start_pos.0, + byte_end: span.hi().0 - start.file.start_pos.0, line_start: start.line, line_end: end.line, column_start: start.col.0 + 1, diff --git a/src/libsyntax/json/tests.rs b/src/libsyntax/json/tests.rs deleted file mode 100644 index eb0d9ef3947c8..0000000000000 --- a/src/libsyntax/json/tests.rs +++ /dev/null @@ -1,186 +0,0 @@ -use super::*; - -use crate::json::JsonEmitter; -use crate::source_map::{FilePathMapping, SourceMap}; -use crate::tests::Shared; -use crate::with_default_globals; - -use errors::emitter::{ColorConfig, HumanReadableErrorType}; -use errors::Handler; -use rustc_serialize::json::decode; -use syntax_pos::{BytePos, Span}; - -use std::str; - -#[derive(RustcDecodable, Debug, PartialEq, Eq)] -struct TestData { - spans: Vec, -} - -#[derive(RustcDecodable, Debug, PartialEq, Eq)] -struct SpanTestData { - pub byte_start: u32, - pub byte_end: u32, - pub line_start: u32, - pub column_start: u32, - pub line_end: u32, - pub column_end: u32, -} - -/// Test the span yields correct positions in JSON. -fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) { - let expected_output = TestData { spans: vec![expected_output] }; - - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned()); - - let output = Arc::new(Mutex::new(Vec::new())); - let je = JsonEmitter::new( - Box::new(Shared { data: output.clone() }), - None, - sm, - true, - HumanReadableErrorType::Short(ColorConfig::Never), - false, - ); - - let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1)); - let handler = Handler::with_emitter(true, None, Box::new(je)); - handler.span_err(span, "foo"); - - let bytes = output.lock().unwrap(); - let actual_output = str::from_utf8(&bytes).unwrap(); - let actual_output: TestData = decode(actual_output).unwrap(); - - assert_eq!(expected_output, actual_output) - }) -} - -#[test] -fn empty() { - test_positions( - " ", - (0, 1), - SpanTestData { - byte_start: 0, - byte_end: 1, - line_start: 1, - column_start: 1, - line_end: 1, - column_end: 2, - }, - ) -} - -#[test] -fn bom() { - test_positions( - "\u{feff} ", - (0, 1), - SpanTestData { - byte_start: 3, - byte_end: 4, - line_start: 1, - column_start: 1, - line_end: 1, - column_end: 2, - }, - ) -} - -#[test] -fn lf_newlines() { - test_positions( - "\nmod foo;\nmod bar;\n", - (5, 12), - SpanTestData { - byte_start: 5, - byte_end: 12, - line_start: 2, - column_start: 5, - line_end: 3, - column_end: 3, - }, - ) -} - -#[test] -fn crlf_newlines() { - test_positions( - "\r\nmod foo;\r\nmod bar;\r\n", - (5, 12), - SpanTestData { - byte_start: 6, - byte_end: 14, - line_start: 2, - column_start: 5, - line_end: 3, - column_end: 3, - }, - ) -} - -#[test] -fn crlf_newlines_with_bom() { - test_positions( - "\u{feff}\r\nmod foo;\r\nmod bar;\r\n", - (5, 12), - SpanTestData { - byte_start: 9, - byte_end: 17, - line_start: 2, - column_start: 5, - line_end: 3, - column_end: 3, - }, - ) -} - -#[test] -fn span_before_crlf() { - test_positions( - "foo\r\nbar", - (2, 3), - SpanTestData { - byte_start: 2, - byte_end: 3, - line_start: 1, - column_start: 3, - line_end: 1, - column_end: 4, - }, - ) -} - -#[test] -fn span_on_crlf() { - test_positions( - "foo\r\nbar", - (3, 4), - SpanTestData { - byte_start: 3, - byte_end: 5, - line_start: 1, - column_start: 4, - line_end: 2, - column_end: 1, - }, - ) -} - -#[test] -fn span_after_crlf() { - test_positions( - "foo\r\nbar", - (4, 5), - SpanTestData { - byte_start: 5, - byte_end: 6, - line_start: 2, - column_start: 1, - line_end: 2, - column_end: 2, - }, - ) -} diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 3a2af96f7db64..2c10220c766a8 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -12,16 +12,21 @@ #![feature(const_transmute)] #![feature(crate_visibility_modifier)] #![feature(label_break_value)] +#![feature(mem_take)] #![feature(nll)] +#![feature(proc_macro_diagnostic)] +#![feature(proc_macro_internals)] +#![feature(proc_macro_span)] #![feature(try_trait)] -#![feature(slice_patterns)] #![feature(unicode_internals)] #![recursion_limit="256"] +extern crate proc_macro; + pub use errors; use rustc_data_structures::sync::Lock; -use rustc_index::bit_set::GrowableBitSet; +use rustc_data_structures::bit_set::GrowableBitSet; pub use rustc_data_structures::thin_vec::ThinVec; use ast::AttrId; use syntax_pos::edition::Edition; @@ -29,7 +34,43 @@ use syntax_pos::edition::Edition; #[cfg(test)] mod tests; -pub const MACRO_ARGUMENTS: Option<&'static str> = Some("macro arguments"); +const MACRO_ARGUMENTS: Option<&'static str> = Some("macro arguments"); + +// A variant of 'try!' that panics on an Err. This is used as a crutch on the +// way towards a non-panic!-prone parser. It should be used for fatal parsing +// errors; eventually we plan to convert all code using panictry to just use +// normal try. +#[macro_export] +macro_rules! panictry { + ($e:expr) => ({ + use std::result::Result::{Ok, Err}; + use errors::FatalError; + match $e { + Ok(e) => e, + Err(mut e) => { + e.emit(); + FatalError.raise() + } + } + }) +} + +// A variant of 'panictry!' that works on a Vec instead of a single DiagnosticBuilder. +macro_rules! panictry_buffer { + ($handler:expr, $e:expr) => ({ + use std::result::Result::{Ok, Err}; + use errors::FatalError; + match $e { + Ok(e) => e, + Err(errs) => { + for e in errs { + $handler.emit_diagnostic(&e); + } + FatalError.raise() + } + } + }) +} #[macro_export] macro_rules! unwrap_or { @@ -50,7 +91,7 @@ pub struct Globals { impl Globals { fn new(edition: Edition) -> Globals { Globals { - // We have no idea how many attributes there will be, so just + // We have no idea how many attributes their will be, so just // initiate the vectors with 0 bits. We'll grow them as necessary. used_attrs: Lock::new(GrowableBitSet::new_empty()), known_attrs: Lock::new(GrowableBitSet::new_empty()), @@ -106,7 +147,6 @@ pub mod ptr; pub mod show_span; pub use syntax_pos::edition; pub use syntax_pos::symbol; -pub mod sess; pub mod tokenstream; pub mod visit; @@ -116,4 +156,19 @@ pub mod print { mod helpers; } +pub mod ext { + mod placeholders; + mod proc_macro_server; + + pub use syntax_pos::hygiene; + pub use mbe::macro_rules::compile_declarative_macro; + pub mod allocator; + pub mod base; + pub mod build; + pub mod expand; + pub mod proc_macro; + + crate mod mbe; +} + pub mod early_buffered_lints; diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 60ee17d09b755..43b5df38e143c 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -550,8 +550,7 @@ pub fn noop_visit_local(local: &mut P, vis: &mut T) { } pub fn noop_visit_attribute(attr: &mut Attribute, vis: &mut T) { - let Attribute { item: AttrItem { path, tokens }, id: _, style: _, is_sugared_doc: _, span } - = attr; + let Attribute { id: _, style: _, path, tokens, is_sugared_doc: _, span } = attr; vis.visit_path(path); vis.visit_tts(tokens); vis.visit_span(span); @@ -610,8 +609,10 @@ pub fn noop_visit_tt(tt: &mut TokenTree, vis: &mut T) { } pub fn noop_visit_tts(TokenStream(tts): &mut TokenStream, vis: &mut T) { - let tts = Lrc::make_mut(tts); - visit_vec(tts, |(tree, _is_joint)| vis.visit_tt(tree)); + visit_opt(tts, |tts| { + let tts = Lrc::make_mut(tts); + visit_vec(tts, |(tree, _is_joint)| vis.visit_tt(tree)); + }) } // Applies ident visitor if it's an ident; applies other visits to interpolated nodes. @@ -680,10 +681,7 @@ pub fn noop_visit_interpolated(nt: &mut token::Nonterminal, vis: token::NtIdent(ident, _is_raw) => vis.visit_ident(ident), token::NtLifetime(ident) => vis.visit_ident(ident), token::NtLiteral(expr) => vis.visit_expr(expr), - token::NtMeta(AttrItem { path, tokens }) => { - vis.visit_path(path); - vis.visit_tts(tokens); - } + token::NtMeta(meta) => vis.visit_meta_item(meta), token::NtPath(path) => vis.visit_path(path), token::NtTT(tt) => vis.visit_tt(tt), token::NtImplItem(item) => @@ -719,7 +717,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 } = decl.deref_mut(); + let FnDecl { inputs, output, c_variadic: _ } = decl.deref_mut(); inputs.flat_map_in_place(|param| vis.flat_map_param(param)); match output { FunctionRetTy::Default(span) => vis.visit_span(span), diff --git a/src/libsyntax/parse/parser/attr.rs b/src/libsyntax/parse/attr.rs similarity index 83% rename from src/libsyntax/parse/parser/attr.rs rename to src/libsyntax/parse/attr.rs index 188a144cac9de..44688bd36b5fb 100644 --- a/src/libsyntax/parse/parser/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -1,11 +1,13 @@ -use super::{SeqSep, PResult, Parser, TokenType, PathStyle}; use crate::attr; use crate::ast; +use crate::parse::{SeqSep, PResult}; use crate::parse::token::{self, Nonterminal, DelimToken}; +use crate::parse::parser::{Parser, TokenType, PathStyle}; use crate::tokenstream::{TokenStream, TokenTree}; use crate::source_map::Span; use log::debug; +use smallvec::smallvec; #[derive(Debug)] enum InnerAttributeParsePolicy<'a> { @@ -18,7 +20,7 @@ const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ impl<'a> Parser<'a> { /// Parses attributes that appear before an item. - pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, Vec> { + crate fn parse_outer_attributes(&mut self) -> PResult<'a, Vec> { let mut attrs: Vec = Vec::new(); let mut just_parsed_doc_comment = false; loop { @@ -82,14 +84,13 @@ impl<'a> Parser<'a> { /// The same as `parse_attribute`, except it takes in an `InnerAttributeParsePolicy` /// that prescribes how to handle inner attributes. - fn parse_attribute_with_inner_parse_policy( - &mut self, - inner_parse_policy: InnerAttributeParsePolicy<'_> - ) -> PResult<'a, ast::Attribute> { + fn parse_attribute_with_inner_parse_policy(&mut self, + inner_parse_policy: InnerAttributeParsePolicy<'_>) + -> PResult<'a, ast::Attribute> { debug!("parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}", inner_parse_policy, self.token); - let (span, item, style) = match self.token.kind { + let (span, path, tokens, style) = match self.token.kind { token::Pound => { let lo = self.token.span; self.bump(); @@ -106,7 +107,7 @@ impl<'a> Parser<'a> { }; self.expect(&token::OpenDelim(token::Bracket))?; - let item = self.parse_attr_item()?; + let (path, tokens) = self.parse_meta_item_unrestricted()?; self.expect(&token::CloseDelim(token::Bracket))?; let hi = self.prev_span; @@ -141,7 +142,7 @@ impl<'a> Parser<'a> { } } - (attr_sp, item, style) + (attr_sp, path, tokens, style) } _ => { let token_str = self.this_token_to_string(); @@ -150,9 +151,10 @@ impl<'a> Parser<'a> { }; Ok(ast::Attribute { - item, id: attr::mk_attr_id(), style, + path, + tokens, is_sugared_doc: false, span, }) @@ -165,19 +167,19 @@ impl<'a> Parser<'a> { /// PATH `[` TOKEN_STREAM `]` /// PATH `{` TOKEN_STREAM `}` /// PATH - /// PATH `=` UNSUFFIXED_LIT + /// PATH `=` TOKEN_TREE /// The delimiters or `=` are still put into the resulting token stream. - pub fn parse_attr_item(&mut self) -> PResult<'a, ast::AttrItem> { - let item = match self.token.kind { + 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 item) => Some(item.clone()), + Nonterminal::NtMeta(ref meta) => Some(meta.clone()), _ => None, }, _ => None, }; - Ok(if let Some(item) = item { + Ok(if let Some(meta) = meta { self.bump(); - item + (meta.path, meta.kind.tokens(meta.span)) } else { let path = self.parse_path(PathStyle::Mod)?; let tokens = if self.check(&token::OpenDelim(DelimToken::Paren)) || @@ -192,19 +194,19 @@ impl<'a> Parser<'a> { is_interpolated_expr = true; } } - let token_tree = if is_interpolated_expr { + let tokens = if is_interpolated_expr { // We need to accept arbitrary interpolated expressions to continue // supporting things like `doc = $expr` that work on stable. // Non-literal interpolated expressions are rejected after expansion. - self.parse_token_tree() + self.parse_token_tree().into() } else { - self.parse_unsuffixed_lit()?.token_tree() + self.parse_unsuffixed_lit()?.tokens() }; - TokenStream::new(vec![eq.into(), token_tree.into()]) + TokenStream::from_streams(smallvec![eq.into(), tokens]) } else { - TokenStream::default() + TokenStream::empty() }; - ast::AttrItem { path, tokens } + (path, tokens) }) } @@ -259,30 +261,9 @@ impl<'a> Parser<'a> { Ok(lit) } - /// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited. - crate fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> { - self.expect(&token::OpenDelim(token::Paren))?; - - let cfg_predicate = self.parse_meta_item()?; - self.expect(&token::Comma)?; - - // Presumably, the majority of the time there will only be one attr. - let mut expanded_attrs = Vec::with_capacity(1); - - while !self.check(&token::CloseDelim(token::Paren)) { - let lo = self.token.span.lo(); - let item = self.parse_attr_item()?; - expanded_attrs.push((item, self.prev_span.with_lo(lo))); - self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?; - } - - self.expect(&token::CloseDelim(token::Paren))?; - Ok((cfg_predicate, expanded_attrs)) - } - /// Matches the following grammar (per RFC 1559). /// - /// meta_item : PATH ( '=' 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 { @@ -293,14 +274,9 @@ impl<'a> Parser<'a> { _ => None, }; - if let Some(item) = nt_meta { - return match item.meta(item.path.span) { - Some(meta) => { - self.bump(); - Ok(meta) - } - None => self.unexpected(), - } + if let Some(meta) = nt_meta { + self.bump(); + return Ok(meta); } let lo = self.token.span; diff --git a/src/libsyntax/parse/parser/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs similarity index 81% rename from src/libsyntax/parse/parser/diagnostics.rs rename to src/libsyntax/parse/diagnostics.rs index 06982c789db8b..ec5d00e0952d7 100644 --- a/src/libsyntax/parse/parser/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -1,11 +1,10 @@ -use super::{ - BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType, - SeqSep, PResult, Parser -}; use crate::ast::{ self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind, - Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, + Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, VariantData, }; +use crate::feature_gate::{feature_err, UnstableFeatures}; +use crate::parse::{SeqSep, PResult, Parser, ParseSess}; +use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType}; use crate::parse::token::{self, TokenKind}; use crate::print::pprust; use crate::ptr::P; @@ -18,10 +17,8 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError}; use log::{debug, trace}; use std::mem; -const TURBOFISH: &'static str = "use `::<...>` instead of `<...>` to specify type arguments"; - /// Creates a placeholder argument. -pub(super) fn dummy_arg(ident: Ident) -> Param { +crate fn dummy_arg(ident: Ident) -> Param { let pat = P(Pat { id: ast::DUMMY_NODE_ID, kind: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None), @@ -124,7 +121,7 @@ impl Error { } } -pub(super) trait RecoverQPath: Sized + 'static { +pub trait RecoverQPath: Sized + 'static { const PATH_STYLE: PathStyle = PathStyle::Expr; fn to_ty(&self) -> Option>; fn recovered(qself: Option, path: ast::Path) -> Self; @@ -176,43 +173,39 @@ impl<'a> Parser<'a> { self.span_fatal(self.token.span, m) } - crate fn span_fatal>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { + pub fn span_fatal>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { self.sess.span_diagnostic.struct_span_fatal(sp, m) } - pub(super) fn span_fatal_err>( - &self, - sp: S, - err: Error, - ) -> DiagnosticBuilder<'a> { + pub fn span_fatal_err>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> { err.span_err(sp, self.diagnostic()) } - pub(super) fn bug(&self, m: &str) -> ! { + pub fn bug(&self, m: &str) -> ! { self.sess.span_diagnostic.span_bug(self.token.span, m) } - pub(super) fn span_err>(&self, sp: S, m: &str) { + pub fn span_err>(&self, sp: S, m: &str) { self.sess.span_diagnostic.span_err(sp, m) } - pub fn struct_span_err>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { + crate fn struct_span_err>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { self.sess.span_diagnostic.struct_span_err(sp, m) } - pub fn span_bug>(&self, sp: S, m: &str) -> ! { + crate fn span_bug>(&self, sp: S, m: &str) -> ! { self.sess.span_diagnostic.span_bug(sp, m) } - pub(super) fn diagnostic(&self) -> &'a errors::Handler { + crate fn diagnostic(&self) -> &'a errors::Handler { &self.sess.span_diagnostic } - pub(super) fn span_to_snippet(&self, span: Span) -> Result { + crate fn span_to_snippet(&self, span: Span) -> Result { self.sess.source_map().span_to_snippet(span) } - pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a> { + crate fn expected_ident_found(&self) -> DiagnosticBuilder<'a> { let mut err = self.struct_span_err( self.token.span, &format!("expected identifier, found {}", self.this_token_descr()), @@ -243,7 +236,7 @@ impl<'a> Parser<'a> { err } - pub(super) fn expected_one_of_not_found( + pub fn expected_one_of_not_found( &mut self, edible: &[TokenKind], inedible: &[TokenKind], @@ -393,17 +386,14 @@ impl<'a> Parser<'a> { let next_pos = sm.lookup_char_pos(self.token.span.lo()); let op_pos = sm.lookup_char_pos(sp.hi()); - let allow_unstable = self.sess.unstable_features.is_nightly_build(); - if likely_path { err.span_suggestion( sp, "maybe write a path separator here", "::".to_string(), - if allow_unstable { - Applicability::MaybeIncorrect - } else { - Applicability::MachineApplicable + match self.sess.unstable_features { + UnstableFeatures::Disallow => Applicability::MachineApplicable, + _ => Applicability::MaybeIncorrect, }, ); } else if op_pos.line != next_pos.line && maybe_expected_semicolon { @@ -413,13 +403,14 @@ impl<'a> Parser<'a> { ";".to_string(), Applicability::MaybeIncorrect, ); - } else if allow_unstable { - err.span_label(sp, "tried to parse a type due to this type ascription"); - } else { + } else if let UnstableFeatures::Disallow = self.sess.unstable_features { err.span_label(sp, "tried to parse a type due to this"); + } else { + err.span_label(sp, "tried to parse a type due to this type ascription"); } - if allow_unstable { + if let UnstableFeatures::Disallow = self.sess.unstable_features { // Give extra information about type ascription only if it's a nightly compiler. + } else { err.note("`#![feature(type_ascription)]` lets you annotate an expression with a \ type: `: `"); err.note("for more information, see \ @@ -430,7 +421,7 @@ 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. - pub(super) fn eat_to_tokens(&mut self, kets: &[&TokenKind]) { + crate fn eat_to_tokens(&mut self, kets: &[&TokenKind]) { if let Err(ref mut err) = self.parse_seq_to_before_tokens( kets, SeqSep::none(), @@ -448,7 +439,7 @@ impl<'a> Parser<'a> { /// let _ = vec![1, 2, 3].into_iter().collect::>>>(); /// ^^ help: remove extra angle brackets /// ``` - pub(super) fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: TokenKind) { + crate fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: TokenKind) { // This function is intended to be invoked after parsing a path segment where there are two // cases: // @@ -552,157 +543,38 @@ impl<'a> Parser<'a> { } /// 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 (see `fn precedence`) and are left-associative (see `fn fixity`). - /// - /// This can also be hit if someone incorrectly writes `foo()` when they should have used - /// the turbofish (`foo::()`) syntax. We attempt some heuristic recovery if that is the - /// case. - /// - /// Keep in mind that given that `outer_op.is_comparison()` holds and comparison ops are left - /// associative we can infer that we have: - /// - /// outer_op - /// / \ - /// inner_op r2 - /// / \ - /// l1 r1 - pub(super) fn check_no_chained_comparison( - &mut self, - lhs: &Expr, - outer_op: &AssocOp, - ) -> PResult<'a, Option>> { - debug_assert!( - outer_op.is_comparison(), - "check_no_chained_comparison: {:?} is not comparison", - outer_op, - ); - - let mk_err_expr = |this: &Self, span| { - Ok(Some(this.mk_expr(span, ExprKind::Err, ThinVec::new()))) - }; - + /// 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.kind { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { // Respan to include both operators. - let op_span = op.span.to(self.prev_span); + let op_span = op.span.to(self.token.span); let mut err = self.struct_span_err( op_span, "chained comparison operators require parentheses", ); - - let suggest = |err: &mut DiagnosticBuilder<'_>| { - err.span_suggestion_verbose( - op_span.shrink_to_lo(), - TURBOFISH, - "::".to_string(), - Applicability::MaybeIncorrect, - ); - }; - if op.node == BinOpKind::Lt && *outer_op == AssocOp::Less || // Include `<` to provide this recommendation *outer_op == AssocOp::Greater // even in a case like the following: { // Foo>> - if *outer_op == AssocOp::Less { - let snapshot = self.clone(); - self.bump(); - // So far we have parsed `foo(` or `foo< bar >::`, so we rewind the - // parser and bail out. - mem::replace(self, snapshot.clone()); - } - } - return if token::ModSep == self.token.kind { - // We have some certainty that this was a bad turbofish at this point. - // `foo< bar >::` - suggest(&mut err); - - let snapshot = self.clone(); - self.bump(); // `::` - - // Consume the rest of the likely `foo::new()` or return at `foo`. - match self.parse_expr() { - Ok(_) => { - // 99% certain that the suggestion is correct, continue parsing. - err.emit(); - // FIXME: actually check that the two expressions in the binop are - // paths and resynthesize new fn call expression instead of using - // `ExprKind::Err` placeholder. - mk_err_expr(self, lhs.span.to(self.prev_span)) - } - Err(mut expr_err) => { - expr_err.cancel(); - // Not entirely sure now, but we bubble the error up with the - // suggestion. - mem::replace(self, snapshot); - Err(err) - } - } - } else if token::OpenDelim(token::Paren) == self.token.kind { - // We have high certainty that this was a bad turbofish at this point. - // `foo< bar >(` - suggest(&mut err); - // Consume the fn call arguments. - match self.consume_fn_args() { - Err(()) => Err(err), - Ok(()) => { - err.emit(); - // FIXME: actually check that the two expressions in the binop are - // paths and resynthesize new fn call expression instead of using - // `ExprKind::Err` placeholder. - mk_err_expr(self, lhs.span.to(self.prev_span)) - } - } - } else { - // All we know is that this is `foo < bar >` and *nothing* else. Try to - // be helpful, but don't attempt to recover. - err.help(TURBOFISH); - err.help("or use `(...)` if you meant to specify fn arguments"); - // These cases cause too many knock-down errors, bail out (#61329). - Err(err) - }; + 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(None) - } - - fn consume_fn_args(&mut self) -> Result<(), ()> { - let snapshot = self.clone(); - self.bump(); // `(` - - // Consume the fn call arguments. - let modifiers = [ - (token::OpenDelim(token::Paren), 1), - (token::CloseDelim(token::Paren), -1), - ]; - self.consume_tts(1, &modifiers[..]); - - if self.token.kind == token::Eof { - // Not entirely sure that what we consumed were fn arguments, rollback. - mem::replace(self, snapshot); - Err(()) - } else { - // 99% certain that the suggestion is correct, continue parsing. - Ok(()) - } + Ok(()) } - pub(super) fn maybe_report_ambiguous_plus( + crate fn maybe_report_ambiguous_plus( &mut self, allow_plus: bool, impl_dyn_multi: bool, @@ -721,7 +593,55 @@ impl<'a> Parser<'a> { } } - pub(super) fn maybe_recover_from_bad_type_plus( + crate fn maybe_report_invalid_custom_discriminants( + sess: &ParseSess, + variants: &[ast::Variant], + ) { + 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.data { + VariantData::Tuple(..) | VariantData::Struct(..) => false, + VariantData::Unit(..) => true, + }) + .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span)) + .collect::>(); + + if !discriminant_spans.is_empty() && has_fields { + let mut err = feature_err( + sess, + sym::arbitrary_enum_discriminant, + discriminant_spans.clone(), + crate::feature_gate::GateIssue::Language, + "custom discriminant values are not allowed in enums with tuple or struct variants", + ); + for sp in discriminant_spans { + err.span_label(sp, "disallowed custom discriminant"); + } + for variant in variants.iter() { + match &variant.data { + VariantData::Struct(..) => { + err.span_label( + variant.span, + "struct variant defined here", + ); + } + VariantData::Tuple(..) => { + err.span_label( + variant.span, + "tuple variant defined here", + ); + } + VariantData::Unit(..) => {} + } + } + err.emit(); + } + } + + crate fn maybe_recover_from_bad_type_plus( &mut self, allow_plus: bool, ty: &Ty, @@ -775,7 +695,7 @@ impl<'a> Parser<'a> { /// 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. - pub(super) fn maybe_recover_from_bad_qpath( + crate fn maybe_recover_from_bad_qpath( &mut self, base: P, allow_recovery: bool, @@ -791,7 +711,7 @@ impl<'a> Parser<'a> { /// Given an already parsed `Ty`, parses the `::AssocItem` tail and /// combines them into a `::AssocItem` expression/pattern/type. - pub(super) fn maybe_recover_from_bad_qpath_stage_2( + crate fn maybe_recover_from_bad_qpath_stage_2( &mut self, ty_span: Span, ty: P, @@ -814,7 +734,7 @@ impl<'a> Parser<'a> { // This is a best-effort recovery. path.span, "try", - format!("<{}>::{}", ty_str, pprust::path_to_string(&path)), + format!("<{}>::{}", ty_str, path), Applicability::MaybeIncorrect, ) .emit(); @@ -830,7 +750,7 @@ impl<'a> Parser<'a> { ))) } - pub(super) fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { + crate fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { if self.eat(&token::Semi) { let mut err = self.struct_span_err(self.prev_span, "expected item, found `;`"); err.span_suggestion_short( @@ -866,7 +786,7 @@ impl<'a> Parser<'a> { /// Creates a `DiagnosticBuilder` for an unexpected token `t` and tries to recover if it is a /// closing delimiter. - pub(super) fn unexpected_try_recover( + pub fn unexpected_try_recover( &mut self, t: &TokenKind, ) -> PResult<'a, bool /* recovered */> { @@ -916,7 +836,7 @@ impl<'a> Parser<'a> { Err(err) } - pub(super) fn parse_semi_or_incorrect_foreign_fn_body( + crate fn parse_semi_or_incorrect_foreign_fn_body( &mut self, ident: &Ident, extern_sp: Span, @@ -954,7 +874,7 @@ impl<'a> Parser<'a> { /// Consumes alternative await syntaxes like `await!()`, `await `, /// `await? `, `await()`, and `await { }`. - pub(super) fn parse_incorrect_await_syntax( + crate fn parse_incorrect_await_syntax( &mut self, lo: Span, await_sp: Span, @@ -1006,7 +926,7 @@ impl<'a> Parser<'a> { } /// If encountering `future.await()`, consumes and emits an error. - pub(super) fn recover_from_await_method_call(&mut self) { + 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)) { @@ -1029,7 +949,7 @@ impl<'a> Parser<'a> { /// and suggest writing `for $pat in $expr` instead. /// /// This should be called before parsing the `$block`. - pub(super) fn recover_parens_around_for_head( + crate fn recover_parens_around_for_head( &mut self, pat: P, expr: &Expr, @@ -1067,7 +987,7 @@ impl<'a> Parser<'a> { } } - pub(super) fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool { + crate fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool { self.token.is_ident() && if let ast::ExprKind::Path(..) = node { true } else { false } && !self.token.is_reserved_ident() && // v `foo:bar(baz)` @@ -1081,7 +1001,7 @@ impl<'a> Parser<'a> { self.look_ahead(2, |t| t == &token::Lt)) // `foo:bar::` } - pub(super) fn recover_seq_parse_error( + crate fn recover_seq_parse_error( &mut self, delim: token::DelimToken, lo: Span, @@ -1098,7 +1018,7 @@ impl<'a> Parser<'a> { } } - pub(super) fn recover_closing_delimiter( + crate fn recover_closing_delimiter( &mut self, tokens: &[TokenKind], mut err: DiagnosticBuilder<'a>, @@ -1149,7 +1069,7 @@ impl<'a> Parser<'a> { } /// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid. - pub(super) fn eat_bad_pub(&mut self) { + crate fn eat_bad_pub(&mut self) { if self.token.is_keyword(kw::Pub) { match self.parse_visibility(false) { Ok(vis) => { @@ -1167,7 +1087,7 @@ impl<'a> Parser<'a> { /// statement. This is something of a best-effort heuristic. /// /// We terminate when we find an unmatched `}` (without consuming it). - pub(super) fn recover_stmt(&mut self) { + crate fn recover_stmt(&mut self) { self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore) } @@ -1178,11 +1098,7 @@ impl<'a> Parser<'a> { /// /// If `break_on_block` is `Break`, then we will stop consuming tokens /// after finding (and consuming) a brace-delimited block. - pub(super) fn recover_stmt_( - &mut self, - break_on_semi: SemiColonMode, - break_on_block: BlockMode, - ) { + crate fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) { let mut brace_depth = 0; let mut bracket_depth = 0; let mut in_block = false; @@ -1250,7 +1166,7 @@ impl<'a> Parser<'a> { } } - pub(super) fn check_for_for_in_in_typo(&mut self, in_span: Span) { + crate fn check_for_for_in_in_typo(&mut self, in_span: Span) { if self.eat_keyword(kw::In) { // a common typo: `for _ in in bar {}` self.struct_span_err(self.prev_span, "expected iterable, found keyword `in`") @@ -1264,14 +1180,14 @@ impl<'a> Parser<'a> { } } - pub(super) fn expected_semi_or_open_brace(&mut self) -> PResult<'a, T> { + crate fn expected_semi_or_open_brace(&mut self) -> PResult<'a, ast::TraitItem> { let token_str = self.this_token_descr(); let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str)); err.span_label(self.token.span, "expected `;` or `{`"); Err(err) } - pub(super) fn eat_incorrect_doc_comment_for_param_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, @@ -1299,12 +1215,11 @@ impl<'a> Parser<'a> { } } - pub(super) fn parameter_without_type( + crate fn parameter_without_type( &mut self, err: &mut DiagnosticBuilder<'_>, pat: P, require_name: bool, - is_self_allowed: bool, is_trait_item: bool, ) -> Option { // If we find a pattern followed by an identifier, it could be an (incorrect) @@ -1326,27 +1241,14 @@ impl<'a> Parser<'a> { if require_name && ( is_trait_item || self.token == token::Comma || - self.token == token::Lt || self.token == token::CloseDelim(token::Paren) - ) { // `fn foo(a, b) {}`, `fn foo(a, b) {}` or `fn foo(usize, usize) {}` - if is_self_allowed { - err.span_suggestion( - pat.span, - "if this is a `self` type, give it a parameter name", - format!("self: {}", ident), - Applicability::MaybeIncorrect, - ); - } - // Avoid suggesting that `fn foo(HashMap)` is fixed with a change to - // `fn foo(HashMap: TypeName)`. - if self.token != token::Lt { - err.span_suggestion( - pat.span, - "if this was a parameter name, give it a type", - format!("{}: TypeName", ident), - Applicability::HasPlaceholders, - ); - } + ) { // `fn foo(a, b) {}` or `fn foo(usize, usize) {}` + err.span_suggestion( + pat.span, + "if this was a parameter name, give it a type", + format!("{}: TypeName", ident), + Applicability::HasPlaceholders, + ); err.span_suggestion( pat.span, "if this is a type, explicitly ignore the parameter name", @@ -1354,15 +1256,13 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ); err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)"); - - // Don't attempt to recover by using the `X` in `X` as the parameter name. - return if self.token == token::Lt { None } else { Some(ident) }; + return Some(ident); } } None } - pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P, P)> { + crate fn recover_arg_parse(&mut self) -> PResult<'a, (P, P)> { let pat = self.parse_pat(Some("argument name"))?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; @@ -1390,7 +1290,7 @@ impl<'a> Parser<'a> { Ok((pat, ty)) } - pub(super) fn recover_bad_self_param( + crate fn recover_bad_self_param( &mut self, mut param: ast::Param, is_trait_item: bool, @@ -1408,7 +1308,7 @@ impl<'a> Parser<'a> { Ok(param) } - pub(super) fn consume_block(&mut self, delim: token::DelimToken) { + crate fn consume_block(&mut self, delim: token::DelimToken) { let mut brace_depth = 0; loop { if self.eat(&token::OpenDelim(delim)) { @@ -1428,7 +1328,7 @@ impl<'a> Parser<'a> { } } - pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a> { + crate fn expected_expression_found(&self) -> DiagnosticBuilder<'a> { let (span, msg) = match (&self.token.kind, self.subparser_name) { (&token::Eof, Some(origin)) => { let sp = self.sess.source_map().next_point(self.token.span); @@ -1448,23 +1348,6 @@ impl<'a> Parser<'a> { err } - fn consume_tts( - &mut self, - mut acc: i64, // `i64` because malformed code can have more closing delims than opening. - // Not using `FxHashMap` due to `token::TokenKind: !Eq + !Hash`. - modifier: &[(token::TokenKind, i64)], - ) { - while acc > 0 { - if let Some((_, val)) = modifier.iter().find(|(t, _)| *t == self.token.kind) { - acc += *val; - } - if self.token.kind == token::Eof { - break; - } - self.bump(); - } - } - /// 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 @@ -1473,7 +1356,7 @@ impl<'a> Parser<'a> { /// 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 parameter names. - pub(super) fn deduplicate_recovered_params_names(&self, fn_inputs: &mut Vec) { + 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/comments.rs b/src/libsyntax/parse/lexer/comments.rs index ac79ce323bf97..5121a9ef7b5fc 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -176,7 +176,7 @@ fn split_block_comment_into_lines( // it appears this function is called only from pprust... that's // probably not a good thing. -crate fn gather_comments(sess: &ParseSess, path: FileName, src: String) -> Vec { +pub fn gather_comments(sess: &ParseSess, path: FileName, src: String) -> Vec { let cm = SourceMap::new(sess.source_map().path_mapping().clone()); let source_file = cm.new_source_file(path, src); let text = (*source_file.src.as_ref().unwrap()).clone(); diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index e6dc9a4c13417..66add869359d8 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1,5 +1,5 @@ +use crate::parse::ParseSess; use crate::parse::token::{self, Token, TokenKind}; -use crate::sess::ParseSess; use crate::symbol::{sym, Symbol}; use crate::parse::unescape_error_reporting::{emit_unescape_error, push_escaped_char}; @@ -47,7 +47,7 @@ impl<'a> StringReader<'a> { source_file: Lrc, override_span: Option) -> Self { if source_file.src.is_none() { - sess.span_diagnostic.bug(&format!("cannot lex `source_file` without source: {}", + sess.span_diagnostic.bug(&format!("Cannot lex source_file without source: {}", source_file.name)); } diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index 853723de14f44..e5ba7e45309dd 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -1,9 +1,7 @@ -use rustc_data_structures::fx::FxHashMap; use syntax_pos::Span; -use super::{StringReader, UnmatchedBrace}; - use crate::print::pprust::token_to_string; +use crate::parse::lexer::{StringReader, UnmatchedBrace}; use crate::parse::token::{self, Token}; use crate::parse::PResult; use crate::tokenstream::{DelimSpan, IsJoint::{self, *}, TokenStream, TokenTree, TreeAndJoint}; @@ -18,7 +16,6 @@ impl<'a> StringReader<'a> { unmatched_braces: Vec::new(), matching_delim_spans: Vec::new(), last_unclosed_found_span: None, - last_delim_empty_block_spans: FxHashMap::default() }; let res = tt_reader.parse_all_token_trees(); (res, tt_reader.unmatched_braces) @@ -37,7 +34,6 @@ struct TokenTreesReader<'a> { /// Used only for error recovery when arriving to EOF with mismatched braces. matching_delim_spans: Vec<(token::DelimToken, Span, Span)>, last_unclosed_found_span: Option, - last_delim_empty_block_spans: FxHashMap } impl<'a> TokenTreesReader<'a> { @@ -125,20 +121,13 @@ impl<'a> TokenTreesReader<'a> { // Correct delimiter. token::CloseDelim(d) if d == delim => { let (open_brace, open_brace_span) = self.open_braces.pop().unwrap(); - let close_brace_span = self.token.span; - - if tts.is_empty() { - let empty_block_span = open_brace_span.to(close_brace_span); - self.last_delim_empty_block_spans.insert(delim, empty_block_span); - } - if self.open_braces.len() == 0 { // Clear up these spans to avoid suggesting them as we've found // properly matched delimiters so far for an entire block. self.matching_delim_spans.clear(); } else { self.matching_delim_spans.push( - (open_brace, open_brace_span, close_brace_span), + (open_brace, open_brace_span, self.token.span), ); } // Parse the close delimiter. @@ -204,20 +193,13 @@ impl<'a> TokenTreesReader<'a> { tts.into() ).into()) }, - token::CloseDelim(delim) => { + token::CloseDelim(_) => { // An unexpected closing delimiter (i.e., there is no // matching opening delimiter). let token_str = token_to_string(&self.token); let msg = format!("unexpected close delimiter: `{}`", token_str); let mut err = self.string_reader.sess.span_diagnostic .struct_span_err(self.token.span, &msg); - - if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) { - err.span_label( - span, - "this block is empty, you might have not meant to close it" - ); - } err.span_label(self.token.span, "unexpected close delimiter"); Err(err) }, diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index 7952e293a532d..fcd5b2782fd61 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -1,10 +1,14 @@ //! Code related to parsing literals. use crate::ast::{self, Lit, LitKind}; -use crate::parse::token::{self, Token}; +use crate::parse::parser::Parser; +use crate::parse::PResult; +use crate::parse::token::{self, Token, TokenKind}; +use crate::print::pprust; use crate::symbol::{kw, sym, Symbol}; -use crate::tokenstream::TokenTree; +use crate::tokenstream::{TokenStream, TokenTree}; +use errors::{Applicability, Handler}; use log::debug; use rustc_data_structures::sync::Lrc; use syntax_pos::Span; @@ -24,6 +28,72 @@ crate enum LitError { IntTooLarge, } +impl LitError { + fn report(&self, diag: &Handler, lit: token::Lit, span: Span) { + let token::Lit { kind, suffix, .. } = lit; + match *self { + // `NotLiteral` is not an error by itself, so we don't report + // it and give the parser opportunity to try something else. + LitError::NotLiteral => {} + // `LexerError` *is* an error, but it was already reported + // by lexer, so here we don't report it the second time. + LitError::LexerError => {} + LitError::InvalidSuffix => { + expect_no_suffix( + diag, span, &format!("{} {} literal", kind.article(), kind.descr()), suffix + ); + } + LitError::InvalidIntSuffix => { + let suf = suffix.expect("suffix error with no suffix").as_str(); + if looks_like_width_suffix(&['i', 'u'], &suf) { + // If it looks like a width, try to be helpful. + let msg = format!("invalid width `{}` for integer literal", &suf[1..]); + diag.struct_span_err(span, &msg) + .help("valid widths are 8, 16, 32, 64 and 128") + .emit(); + } else { + let msg = format!("invalid suffix `{}` for integer literal", suf); + diag.struct_span_err(span, &msg) + .span_label(span, format!("invalid suffix `{}`", suf)) + .help("the suffix must be one of the integral types (`u32`, `isize`, etc)") + .emit(); + } + } + LitError::InvalidFloatSuffix => { + let suf = suffix.expect("suffix error with no suffix").as_str(); + if looks_like_width_suffix(&['f'], &suf) { + // If it looks like a width, try to be helpful. + let msg = format!("invalid width `{}` for float literal", &suf[1..]); + diag.struct_span_err(span, &msg) + .help("valid widths are 32 and 64") + .emit(); + } else { + let msg = format!("invalid suffix `{}` for float literal", suf); + diag.struct_span_err(span, &msg) + .span_label(span, format!("invalid suffix `{}`", suf)) + .help("valid suffixes are `f32` and `f64`") + .emit(); + } + } + LitError::NonDecimalFloat(base) => { + let descr = match base { + 16 => "hexadecimal", + 8 => "octal", + 2 => "binary", + _ => unreachable!(), + }; + diag.struct_span_err(span, &format!("{} float literal is not supported", descr)) + .span_label(span, "not supported") + .emit(); + } + LitError::IntTooLarge => { + diag.struct_span_err(span, "integer literal is too large") + .emit(); + } + } + } +} + impl LitKind { /// Converts literal token into a semantic literal. fn from_lit_token(lit: token::Lit) -> Result { @@ -134,7 +204,7 @@ impl LitKind { let (kind, symbol, suffix) = match *self { LitKind::Str(symbol, ast::StrStyle::Cooked) => { // Don't re-intern unless the escaped string is different. - let s: &str = &symbol.as_str(); + let s = &symbol.as_str(); let escaped = s.escape_default().to_string(); let symbol = if escaped == *s { symbol } else { Symbol::intern(&escaped) }; (token::Str, symbol, None) @@ -184,7 +254,7 @@ impl LitKind { impl Lit { /// Converts literal token into an AST literal. - crate fn from_lit_token(token: token::Lit, span: Span) -> Result { + fn from_lit_token(token: token::Lit, span: Span) -> Result { Ok(Lit { token, kind: LitKind::from_lit_token(token)?, span }) } @@ -216,16 +286,109 @@ impl Lit { Lit { token: kind.to_lit_token(), kind, span } } - /// Losslessly convert an AST literal into a token tree. - crate fn token_tree(&self) -> TokenTree { + /// Losslessly convert an AST literal into a token stream. + crate fn tokens(&self) -> TokenStream { let token = match self.token.kind { token::Bool => token::Ident(self.token.symbol, false), _ => token::Literal(self.token), }; - TokenTree::token(token, self.span) + TokenTree::token(token, self.span).into() } } +impl<'a> Parser<'a> { + /// Matches `lit = true | false | token_lit`. + crate fn parse_lit(&mut self) -> PResult<'a, Lit> { + let mut recovered = None; + if self.token == token::Dot { + // Attempt to recover `.4` as `0.4`. + recovered = self.look_ahead(1, |next_token| { + if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) + = next_token.kind { + if self.token.span.hi() == next_token.span.lo() { + let s = String::from("0.") + &symbol.as_str(); + let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix); + return Some(Token::new(kind, self.token.span.to(next_token.span))); + } + } + None + }); + if let Some(token) = &recovered { + self.bump(); + self.diagnostic() + .struct_span_err(token.span, "float literals must have an integer part") + .span_suggestion( + token.span, + "must have an integer part", + pprust::token_to_string(token), + Applicability::MachineApplicable, + ) + .emit(); + } + } + + let token = recovered.as_ref().unwrap_or(&self.token); + match Lit::from_token(token) { + Ok(lit) => { + self.bump(); + Ok(lit) + } + Err(LitError::NotLiteral) => { + let msg = format!("unexpected token: {}", self.this_token_descr()); + Err(self.span_fatal(token.span, &msg)) + } + Err(err) => { + let (lit, span) = (token.expect_lit(), token.span); + self.bump(); + err.report(&self.sess.span_diagnostic, lit, span); + // Pack possible quotes and prefixes from the original literal into + // the error literal's symbol so they can be pretty-printed faithfully. + let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); + let symbol = Symbol::intern(&suffixless_lit.to_string()); + let lit = token::Lit::new(token::Err, symbol, lit.suffix); + Lit::from_lit_token(lit, span).map_err(|_| unreachable!()) + } + } + } +} + +crate fn expect_no_suffix(diag: &Handler, sp: Span, kind: &str, suffix: Option) { + if let Some(suf) = suffix { + let mut err = if kind == "a tuple index" && + [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suf) { + // #59553: warn instead of reject out of hand to allow the fix to percolate + // through the ecosystem when people fix their macros + let mut err = diag.struct_span_warn( + sp, + &format!("suffixes on {} are invalid", kind), + ); + err.note(&format!( + "`{}` is *temporarily* accepted on tuple index fields as it was \ + incorrectly accepted on stable for a few releases", + suf, + )); + err.help( + "on proc macros, you'll want to use `syn::Index::from` or \ + `proc_macro::Literal::*_unsuffixed` for code that will desugar \ + to tuple field access", + ); + err.note( + "for more context, see https://github.com/rust-lang/rust/issues/60210", + ); + err + } else { + diag.struct_span_err(sp, &format!("suffixes on {} are invalid", kind)) + }; + err.span_label(sp, format!("invalid suffix `{}`", suf)); + err.emit(); + } +} + +// Checks if `s` looks like i32 or u1234 etc. +fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { + s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) +} + fn strip_underscores(symbol: Symbol) -> Symbol { // Do not allocate a new string unless necessary. let s = symbol.as_str(); @@ -263,12 +426,15 @@ fn integer_lit(symbol: Symbol, suffix: Option) -> Result 16, - [b'0', b'o', ..] => 8, - [b'0', b'b', ..] => 2, - _ => 10, - }; + let mut base = 10; + if s.len() > 1 && s.as_bytes()[0] == b'0' { + match s.as_bytes()[1] { + b'x' => base = 16, + b'o' => base = 8, + b'b' => base = 2, + _ => {} + } + } let ty = match suffix { Some(suf) => match suf { diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index e6ddf8778ccf0..fa4c10431228a 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -1,33 +1,40 @@ //! The main parser interface. -use crate::ast; -use crate::parse::parser::{Parser, emit_unclosed_delims}; -use crate::parse::token::Nonterminal; -use crate::tokenstream::{self, TokenStream, TokenTree}; +use crate::ast::{self, CrateConfig, NodeId}; +use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId}; +use crate::source_map::{SourceMap, FilePathMapping}; +use crate::feature_gate::UnstableFeatures; +use crate::parse::parser::Parser; +use crate::parse::parser::emit_unclosed_delims; +use crate::parse::token::TokenKind; +use crate::tokenstream::{TokenStream, TokenTree}; use crate::print::pprust; -use crate::sess::ParseSess; +use crate::symbol::Symbol; -use errors::{FatalError, Level, Diagnostic, DiagnosticBuilder}; +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; -use syntax_pos::{Span, SourceFile, FileName}; +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 std::borrow::Cow; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::str; -use log::info; - #[cfg(test)] mod tests; #[macro_use] pub mod parser; +pub mod attr; pub mod lexer; pub mod token; crate mod classify; +crate mod diagnostics; crate mod literal; crate mod unescape_error_reporting; @@ -38,6 +45,110 @@ pub type PResult<'a, T> = Result>; #[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, + pub unstable_features: UnstableFeatures, + pub config: CrateConfig, + pub edition: Edition, + pub missing_fragment_specifiers: Lock>, + /// Places where raw identifiers were used. This is used for feature-gating raw identifiers. + pub raw_identifier_spans: Lock>, + /// Used to determine and report recursive module inclusions. + included_mod_stack: Lock>, + source_map: Lrc, + pub buffered_lints: Lock>, + /// Contains the spans of block expressions that could have been incomplete based on the + /// operation token that followed it, but that the parser cannot identify without further + /// analysis. + pub ambiguous_block_expr_parse: 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()), + ); + ParseSess::with_span_handler(handler, cm) + } + + 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()), + included_mod_stack: Lock::new(vec![]), + source_map, + buffered_lints: Lock::new(vec![]), + ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), + injected_crate_name: Once::new(), + gated_spans: GatedSpans::default(), + } + } + + #[inline] + pub fn source_map(&self) -> &SourceMap { + &self.source_map + } + + pub fn buffer_lint>(&self, + lint_id: BufferedEarlyLintId, + span: S, + id: NodeId, + msg: &str, + ) { + self.buffered_lints.with_lock(|buffered_lints| { + buffered_lints.push(BufferedEarlyLint{ + span: span.into(), + id, + msg: msg.into(), + lint_id, + }); + }); + } + + /// Extend an error with a suggestion to wrap an expression with parentheses to allow the + /// parser to continue parsing the following operation as part of the same expression. + pub fn expr_parentheses_needed( + &self, + err: &mut DiagnosticBuilder<'_>, + span: Span, + alt_snippet: Option, + ) { + if let Some(snippet) = self.source_map().span_to_snippet(span).ok().or(alt_snippet) { + err.span_suggestion( + span, + "parentheses are required to parse this as an expression", + format!("({})", snippet), + Applicability::MachineApplicable, + ); + } + } +} + #[derive(Clone)] pub struct Directory<'a> { pub path: Cow<'a, Path>, @@ -59,23 +170,6 @@ pub enum DirectoryOwnership { // uses a HOF to parse anything, and includes file and // `source_str`. -/// A variant of 'panictry!' that works on a Vec instead of a single DiagnosticBuilder. -macro_rules! panictry_buffer { - ($handler:expr, $e:expr) => ({ - use std::result::Result::{Ok, Err}; - use errors::FatalError; - match $e { - Ok(e) => e, - Err(errs) => { - for e in errs { - $handler.emit_diagnostic(&e); - } - FatalError.raise() - } - } - }) -} - 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); parser.parse_crate_mod() @@ -288,131 +382,26 @@ pub fn stream_to_parser_with_base_dir<'a>( Parser::new(sess, stream, Some(base_dir), true, false, None) } -// NOTE(Centril): The following probably shouldn't be here but it acknowledges the -// fact that architecturally, we are using parsing (read on below to understand why). - -pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> TokenStream { - // A `Nonterminal` is often a parsed AST item. At this point we now - // need to convert the parsed AST to an actual token stream, e.g. - // un-parse it basically. - // - // Unfortunately there's not really a great way to do that in a - // guaranteed lossless fashion right now. The fallback here is to just - // stringify the AST node and reparse it, but this loses all span - // information. - // - // As a result, some AST nodes are annotated with the token stream they - // came from. Here we attempt to extract these lossless token streams - // before we fall back to the stringification. - let tokens = match *nt { - Nonterminal::NtItem(ref item) => { - prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) - } - Nonterminal::NtTraitItem(ref item) => { - prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) - } - Nonterminal::NtImplItem(ref item) => { - prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) - } - Nonterminal::NtIdent(ident, is_raw) => { - Some(tokenstream::TokenTree::token(token::Ident(ident.name, is_raw), ident.span).into()) - } - Nonterminal::NtLifetime(ident) => { - Some(tokenstream::TokenTree::token(token::Lifetime(ident.name), ident.span).into()) - } - Nonterminal::NtTT(ref tt) => { - Some(tt.clone().into()) - } - _ => None, - }; - - // FIXME(#43081): Avoid this pretty-print + reparse hack - let source = pprust::nonterminal_to_string(nt); - let filename = FileName::macro_expansion_source_code(&source); - let tokens_for_real = parse_stream_from_source_str(filename, source, sess, Some(span)); - - // During early phases of the compiler the AST could get modified - // directly (e.g., attributes added or removed) and the internal cache - // of tokens my not be invalidated or updated. Consequently if the - // "lossless" token stream disagrees with our actual stringification - // (which has historically been much more battle-tested) then we go - // with the lossy stream anyway (losing span information). - // - // Note that the comparison isn't `==` here to avoid comparing spans, - // but it *also* is a "probable" equality which is a pretty weird - // definition. We mostly want to catch actual changes to the AST - // like a `#[cfg]` being processed or some weird `macro_rules!` - // expansion. - // - // What we *don't* want to catch is the fact that a user-defined - // literal like `0xf` is stringified as `15`, causing the cached token - // stream to not be literal `==` token-wise (ignoring spans) to the - // token stream we got from stringification. - // - // Instead the "probably equal" check here is "does each token - // recursively have the same discriminant?" We basically don't look at - // the token values here and assume that such fine grained token stream - // modifications, including adding/removing typically non-semantic - // tokens such as extra braces and commas, don't happen. - if let Some(tokens) = tokens { - if tokens.probably_equal_for_proc_macro(&tokens_for_real) { - return tokens - } - info!("cached tokens found, but they're not \"probably equal\", \ - going with stringified version"); - } - return tokens_for_real +/// A sequence separator. +pub struct SeqSep { + /// The separator token. + pub sep: Option, + /// `true` if a trailing separator is allowed. + pub trailing_sep_allowed: bool, } -fn prepend_attrs( - sess: &ParseSess, - attrs: &[ast::Attribute], - tokens: Option<&tokenstream::TokenStream>, - span: syntax_pos::Span -) -> Option { - let tokens = tokens?; - if attrs.len() == 0 { - return Some(tokens.clone()) - } - let mut builder = tokenstream::TokenStreamBuilder::new(); - for attr in attrs { - assert_eq!(attr.style, ast::AttrStyle::Outer, - "inner attributes should prevent cached tokens from existing"); - - let source = pprust::attribute_to_string(attr); - let macro_filename = FileName::macro_expansion_source_code(&source); - if attr.is_sugared_doc { - let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span)); - builder.push(stream); - continue +impl SeqSep { + pub fn trailing_allowed(t: TokenKind) -> SeqSep { + SeqSep { + sep: Some(t), + trailing_sep_allowed: true, } + } - // synthesize # [ $path $tokens ] manually here - let mut brackets = tokenstream::TokenStreamBuilder::new(); - - // For simple paths, push the identifier directly - if attr.path.segments.len() == 1 && attr.path.segments[0].args.is_none() { - let ident = attr.path.segments[0].ident; - let token = token::Ident(ident.name, ident.as_str().starts_with("r#")); - brackets.push(tokenstream::TokenTree::token(token, ident.span)); - - // ... and for more complicated paths, fall back to a reparse hack that - // should eventually be removed. - } else { - let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span)); - brackets.push(stream); + pub fn none() -> SeqSep { + SeqSep { + sep: None, + trailing_sep_allowed: false, } - - brackets.push(attr.tokens.clone()); - - // The span we list here for `#` and for `[ ... ]` are both wrong in - // that it encompasses more than each token, but it hopefully is "good - // enough" for now at least. - builder.push(tokenstream::TokenTree::token(token::Pound, attr.span)); - let delim_span = tokenstream::DelimSpan::from_single(attr.span); - builder.push(tokenstream::TokenTree::Delimited( - delim_span, token::DelimToken::Bracket, brackets.build().into())); } - builder.push(tokens.clone()); - Some(builder.build()) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6ead1ce811d49..cc582819b6b61 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1,28 +1,28 @@ -pub mod attr; mod expr; mod pat; mod item; +pub use item::AliasKind; mod module; +pub use module::{ModulePath, ModulePathSuccess}; mod ty; mod path; pub use path::PathStyle; mod stmt; mod generics; -mod diagnostics; -use diagnostics::Error; use crate::ast::{ - self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident, - IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety, + self, DUMMY_NODE_ID, AttrStyle, Attribute, BindingMode, CrateSugar, FnDecl, Ident, + IsAsync, MacDelimiter, Mutability, Param, StrStyle, SelfKind, TyKind, Visibility, + VisibilityKind, Unsafety, }; -use crate::parse::{PResult, Directory, DirectoryOwnership}; +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::{self, Token, TokenKind, DelimToken}; +use crate::parse::token::{Token, TokenKind, DelimToken}; use crate::print::pprust; use crate::ptr::P; -use crate::sess::ParseSess; -use crate::source_map::respan; +use crate::source_map::{self, respan}; use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; use crate::ThinVec; @@ -44,14 +44,14 @@ bitflags::bitflags! { } #[derive(Clone, Copy, PartialEq, Debug)] -enum SemiColonMode { +crate enum SemiColonMode { Break, Ignore, Comma, } #[derive(Clone, Copy, PartialEq, Debug)] -enum BlockMode { +crate enum BlockMode { Break, Ignore, } @@ -86,6 +86,13 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { } } +fn maybe_append(mut lhs: Vec, mut rhs: Option>) -> Vec { + if let Some(ref mut rhs) = rhs { + lhs.append(rhs); + } + lhs +} + #[derive(Debug, Clone, Copy, PartialEq)] enum PrevTokenKind { DocComment, @@ -117,33 +124,33 @@ pub struct Parser<'a> { prev_token_kind: PrevTokenKind, restrictions: Restrictions, /// Used to determine the path to externally loaded source files. - pub(super) directory: Directory<'a>, + crate directory: Directory<'a>, /// `true` to parse sub-modules in other files. - pub(super) recurse_into_file_modules: bool, + pub recurse_into_file_modules: bool, /// Name of the root module this parser originated from. If `None`, then the /// name is not known. This does not change while the parser is descending /// into modules, and sub-parsers have new values for this name. pub root_module_name: Option, - expected_tokens: Vec, + crate expected_tokens: Vec, token_cursor: TokenCursor, desugar_doc_comments: bool, /// `true` we should configure out of line modules as we parse. - cfg_mods: bool, + pub cfg_mods: bool, /// This field is used to keep track of how many left angle brackets we have seen. This is /// required in order to detect extra leading left angle brackets (`<` characters) and error /// appropriately. /// /// See the comments in the `parse_path_segment` function for more details. - unmatched_angle_bracket_count: u32, - max_angle_bracket_count: u32, + crate unmatched_angle_bracket_count: u32, + crate max_angle_bracket_count: u32, /// 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. - pub(super) unclosed_delims: Vec, - last_unexpected_token_span: Option, - pub last_type_ascription: Option<(Span, bool /* likely path typo */)>, + crate unclosed_delims: Vec, + crate last_unexpected_token_span: Option, + crate last_type_ascription: Option<(Span, bool /* likely path typo */)>, /// If present, this `Parser` is not parsing Rust code but rather a macro call. - subparser_name: Option<&'static str>, + crate subparser_name: Option<&'static str>, } impl<'a> Drop for Parser<'a> { @@ -187,7 +194,7 @@ struct TokenCursorFrame { /// You can find some more example usage of this in the `collect_tokens` method /// on the parser. #[derive(Clone)] -enum LastToken { +crate enum LastToken { Collecting(Vec), Was(Option), } @@ -278,10 +285,10 @@ impl TokenCursor { token::NoDelim, &if doc_comment_style(&name.as_str()) == AttrStyle::Inner { [TokenTree::token(token::Pound, sp), TokenTree::token(token::Not, sp), body] - .iter().cloned().collect::() + .iter().cloned().collect::().into() } else { [TokenTree::token(token::Pound, sp), body] - .iter().cloned().collect::() + .iter().cloned().collect::().into() }, ))); @@ -290,7 +297,7 @@ impl TokenCursor { } #[derive(Clone, PartialEq)] -enum TokenType { +crate enum TokenType { Token(TokenKind), Keyword(Symbol), Operator, @@ -302,7 +309,7 @@ enum TokenType { } impl TokenType { - fn to_string(&self) -> String { + crate fn to_string(&self) -> String { match *self { TokenType::Token(ref t) => format!("`{}`", pprust::token_kind_to_string(t)), TokenType::Keyword(kw) => format!("`{}`", kw), @@ -317,35 +324,11 @@ impl TokenType { } #[derive(Copy, Clone, Debug)] -enum TokenExpectType { +crate enum TokenExpectType { Expect, NoExpect, } -/// A sequence separator. -struct SeqSep { - /// The separator token. - sep: Option, - /// `true` if a trailing separator is allowed. - trailing_sep_allowed: bool, -} - -impl SeqSep { - fn trailing_allowed(t: TokenKind) -> SeqSep { - SeqSep { - sep: Some(t), - trailing_sep_allowed: true, - } - } - - fn none() -> SeqSep { - SeqSep { - sep: None, - trailing_sep_allowed: false, - } - } -} - impl<'a> Parser<'a> { pub fn new( sess: &'a ParseSess, @@ -422,7 +405,7 @@ impl<'a> Parser<'a> { pprust::token_to_string(&self.token) } - fn token_descr(&self) -> Option<&'static str> { + crate fn token_descr(&self) -> Option<&'static str> { Some(match &self.token.kind { _ if self.token.is_special_ident() => "reserved identifier", _ if self.token.is_used_keyword() => "keyword", @@ -432,7 +415,7 @@ impl<'a> Parser<'a> { }) } - pub(super) fn this_token_descr(&self) -> String { + crate fn this_token_descr(&self) -> String { if let Some(prefix) = self.token_descr() { format!("{} `{}`", prefix, self.this_token_to_string()) } else { @@ -482,7 +465,7 @@ impl<'a> Parser<'a> { } } - fn parse_ident(&mut self) -> PResult<'a, ast::Ident> { + pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> { self.parse_ident_common(true) } @@ -515,7 +498,7 @@ impl<'a> Parser<'a> { /// /// This method will automatically add `tok` to `expected_tokens` if `tok` is not /// encountered. - fn check(&mut self, tok: &TokenKind) -> bool { + crate fn check(&mut self, tok: &TokenKind) -> bool { let is_present = self.token == *tok; if !is_present { self.expected_tokens.push(TokenType::Token(tok.clone())); } is_present @@ -528,16 +511,14 @@ impl<'a> Parser<'a> { is_present } - /// If the next token is the given keyword, returns `true` without eating it. - /// An expectation is also added for diagnostics purposes. fn check_keyword(&mut self, kw: Symbol) -> bool { self.expected_tokens.push(TokenType::Keyword(kw)); self.token.is_keyword(kw) } - /// If the next token is the given keyword, eats it and returns `true`. - /// Otherwise, returns `false`. An expectation is also added for diagnostics purposes. - fn eat_keyword(&mut self, kw: Symbol) -> bool { + /// If the next token is the given keyword, eats it and returns + /// `true`. Otherwise, returns `false`. + pub fn eat_keyword(&mut self, kw: Symbol) -> bool { if self.check_keyword(kw) { self.bump(); true @@ -566,38 +547,40 @@ impl<'a> Parser<'a> { } } - fn check_or_expected(&mut self, ok: bool, typ: TokenType) -> bool { - if ok { + crate fn check_ident(&mut self) -> bool { + if self.token.is_ident() { true } else { - self.expected_tokens.push(typ); + self.expected_tokens.push(TokenType::Ident); false } } - fn check_ident(&mut self) -> bool { - self.check_or_expected(self.token.is_ident(), TokenType::Ident) - } - fn check_path(&mut self) -> bool { - self.check_or_expected(self.token.is_path_start(), TokenType::Path) + if self.token.is_path_start() { + true + } else { + self.expected_tokens.push(TokenType::Path); + false + } } fn check_type(&mut self) -> bool { - self.check_or_expected(self.token.can_begin_type(), TokenType::Type) + if self.token.can_begin_type() { + true + } else { + self.expected_tokens.push(TokenType::Type); + false + } } fn check_const_arg(&mut self) -> bool { - self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const) - } - - /// Checks to see if the next token is either `+` or `+=`. - /// Otherwise returns `false`. - fn check_plus(&mut self) -> bool { - self.check_or_expected( - self.token.is_like_plus(), - TokenType::Token(token::BinOp(token::Plus)), - ) + if self.token.can_begin_const_arg() { + true + } else { + self.expected_tokens.push(TokenType::Const); + false + } } /// Expects and consumes a `+`. if `+=` is seen, replaces it with a `=` @@ -621,6 +604,18 @@ impl<'a> Parser<'a> { } } + /// Checks to see if the next token is either `+` or `+=`. + /// Otherwise returns `false`. + fn check_plus(&mut self) -> bool { + if self.token.is_like_plus() { + true + } + else { + self.expected_tokens.push(TokenType::Token(token::BinOp(token::Plus))); + false + } + } + /// Expects and consumes an `&`. If `&&` is seen, replaces it with a single /// `&` and continues. If an `&` is not seen, signals an error. fn expect_and(&mut self) -> PResult<'a, ()> { @@ -655,6 +650,10 @@ impl<'a> Parser<'a> { } } + fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option) { + literal::expect_no_suffix(&self.sess.span_diagnostic, sp, kind, suffix) + } + /// Attempts to consume a `<`. If `<<` is seen, replaces it with a single /// `<` and continue. If `<-` is seen, replaces it with a single `<` /// and continue. If a `<` is not seen, returns false. @@ -740,7 +739,7 @@ impl<'a> Parser<'a> { /// Parses a sequence, including the closing delimiter. The function /// `f` must consume tokens until reaching the next separator or /// closing bracket. - fn parse_seq_to_end( + pub fn parse_seq_to_end( &mut self, ket: &TokenKind, sep: SeqSep, @@ -756,7 +755,7 @@ impl<'a> Parser<'a> { /// Parses a sequence, not including the closing delimiter. The function /// `f` must consume tokens until reaching the next separator or /// closing bracket. - fn parse_seq_to_before_end( + pub fn parse_seq_to_before_end( &mut self, ket: &TokenKind, sep: SeqSep, @@ -774,7 +773,7 @@ impl<'a> Parser<'a> { }) } - fn parse_seq_to_before_tokens( + crate fn parse_seq_to_before_tokens( &mut self, kets: &[&TokenKind], sep: SeqSep, @@ -911,15 +910,15 @@ impl<'a> Parser<'a> { self.expected_tokens.clear(); } - /// Look-ahead `dist` tokens of `self.token` and get access to that token there. - /// When `dist == 0` then the current token is looked at. - pub fn look_ahead(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R { + pub fn look_ahead(&self, dist: usize, f: F) -> R where + F: FnOnce(&Token) -> R, + { if dist == 0 { - return looker(&self.token); + return f(&self.token); } let frame = &self.token_cursor.frame; - looker(&match frame.tree_cursor.look_ahead(dist - 1) { + f(&match frame.tree_cursor.look_ahead(dist - 1) { Some(tree) => match tree { TokenTree::Token(token) => token, TokenTree::Delimited(dspan, delim, _) => @@ -955,6 +954,102 @@ impl<'a> Parser<'a> { } } + fn is_named_argument(&self) -> bool { + let offset = match self.token.kind { + token::Interpolated(ref nt) => match **nt { + token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), + _ => 0, + } + token::BinOp(token::And) | token::AndAnd => 1, + _ if self.token.is_keyword(kw::Mut) => 1, + _ => 0, + }; + + self.look_ahead(offset, |t| t.is_ident()) && + self.look_ahead(offset + 1, |t| t == &token::Colon) + } + + /// Skips unexpected attributes and doc comments in this position and emits an appropriate + /// error. + /// This version of parse param doesn't necessarily require identifier names. + fn parse_param_general( + &mut self, + is_trait_item: bool, + allow_c_variadic: bool, + is_name_required: impl Fn(&token::Token) -> bool, + ) -> PResult<'a, Param> { + let lo = self.token.span; + let attrs = self.parse_outer_attributes()?; + if let Some(mut param) = self.parse_self_param()? { + param.attrs = attrs.into(); + return 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_param_general parse_pat (is_name_required:{})", is_name_required); + + let pat = self.parse_fn_param_pat()?; + if let Err(mut err) = self.expect(&token::Colon) { + if let Some(ident) = self.parameter_without_type( + &mut err, + pat, + is_name_required, + is_trait_item, + ) { + err.emit(); + return Ok(dummy_arg(ident)); + } else { + return Err(err); + } + } + + self.eat_incorrect_doc_comment_for_param_type(); + (pat, self.parse_ty_common(true, true, allow_c_variadic)?) + } else { + debug!("parse_param_general ident_to_pat"); + let parser_snapshot_before_ty = self.clone(); + 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) { + // This wasn't actually a type, but a pattern looking like a type, + // so we are going to rollback and re-parse for recovery. + ty = self.unexpected(); + } + match ty { + Ok(ty) => { + let ident = Ident::new(kw::Invalid, self.prev_span); + let bm = BindingMode::ByValue(Mutability::Immutable); + let pat = self.mk_pat_ident(ty.span, bm, ident); + (pat, ty) + } + Err(mut err) => { + // If this is a C-variadic argument and we hit an error, return the + // error. + if self.token == token::DotDotDot { + return Err(err); + } + // Recover from attempting to parse the argument as a type without pattern. + err.cancel(); + mem::replace(self, parser_snapshot_before_ty); + self.recover_arg_parse()? + } + } + }; + + let span = lo.to(self.token.span); + + Ok(Param { + attrs: attrs.into(), + id: ast::DUMMY_NODE_ID, + is_placeholder: false, + pat, + span, + ty, + }) + } + /// Parses mutability (`mut` or nothing). fn parse_mutability(&mut self) -> Mutability { if self.eat_keyword(kw::Mut) { @@ -964,17 +1059,6 @@ impl<'a> Parser<'a> { } } - /// Possibly parses mutability (`const` or `mut`). - fn parse_const_or_mut(&mut self) -> Option { - if self.eat_keyword(kw::Mut) { - Some(Mutability::Mutable) - } else if self.eat_keyword(kw::Const) { - Some(Mutability::Immutable) - } else { - None - } - } - fn parse_field_name(&mut self) -> PResult<'a, Ident> { if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = self.token.kind { @@ -1009,10 +1093,9 @@ impl<'a> Parser<'a> { Ok((delim, tts.into())) } - fn parse_or_use_outer_attributes( - &mut self, - already_parsed_attrs: Option>, - ) -> PResult<'a, ThinVec> { + fn parse_or_use_outer_attributes(&mut self, + already_parsed_attrs: Option>) + -> PResult<'a, ThinVec> { if let Some(attrs) = already_parsed_attrs { Ok(attrs) } else { @@ -1020,7 +1103,7 @@ impl<'a> Parser<'a> { } } - pub fn process_potential_macro_variable(&mut self) { + crate fn process_potential_macro_variable(&mut self) { self.token = match self.token.kind { token::Dollar if self.token.span.from_expansion() && self.look_ahead(1, |t| t.is_ident()) => { @@ -1054,7 +1137,7 @@ impl<'a> Parser<'a> { } /// Parses a single token tree from the input. - pub fn parse_token_tree(&mut self) -> TokenTree { + crate fn parse_token_tree(&mut self) -> TokenTree { match self.token.kind { token::OpenDelim(..) => { let frame = mem::replace(&mut self.token_cursor.frame, @@ -1099,12 +1182,240 @@ impl<'a> Parser<'a> { /// Evaluates the closure with restrictions in place. /// /// Afters the closure is evaluated, restrictions are reset. - fn with_res(&mut self, res: Restrictions, f: impl FnOnce(&mut Self) -> T) -> T { + fn with_res(&mut self, r: Restrictions, f: F) -> T + where F: FnOnce(&mut Self) -> T + { let old = self.restrictions; - self.restrictions = res; - let res = f(self); + self.restrictions = r; + let r = f(self); self.restrictions = old; - res + return r; + + } + + 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 (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_params + } + }; + match p.parse_param_general( + false, + allow_c_variadic, + do_not_enforce_named_arguments_for_c_variadic + ) { + Ok(param) => { + if let TyKind::CVarArgs = param.ty.kind { + c_variadic = true; + if p.token != token::CloseDelim(token::Paren) { + let span = p.token.span; + p.span_err(span, + "`...` must be the last argument of a C-variadic function"); + Ok(None) + } else { + Ok(Some(param)) + } + } else { + Ok(Some(param)) + } + }, + Err(mut e) => { + e.emit(); + let lo = p.prev_span; + // Skip every token until next possible arg or end. + p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); + // Create a placeholder argument for proper arg count (issue #34264). + let span = lo.to(p.prev_span); + Ok(Some(dummy_arg(Ident::new(kw::Invalid, span)))) + } + } + })?; + + let params: Vec<_> = params.into_iter().filter_map(|x| x).collect(); + + if c_variadic && params.len() <= 1 { + self.span_err(sp, + "C-variadic function must be declared with at least one named argument"); + } + + Ok((params, c_variadic)) + } + + /// Returns the parsed optional self parameter and whether a self shortcut was used. + /// + /// 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, _) => + { let span = this.token.span; this.bump(); Ident::new(name, span) } + _ => unreachable!() + }; + let isolated_self = |this: &mut Self, n| { + this.look_ahead(n, |t| t.is_keyword(kw::SelfLower)) && + this.look_ahead(n + 1, |t| t != &token::ModSep) + }; + + // Parse optional `self` parameter of a method. + // Only a limited set of initial token sequences is considered `self` parameters; anything + // else is parsed as a normal function parameter list, so some lookahead is required. + let eself_lo = self.token.span; + let (eself, eself_ident, eself_hi) = match self.token.kind { + token::BinOp(token::And) => { + // `&self` + // `&mut self` + // `&'lt self` + // `&'lt mut self` + // `¬_self` + (if isolated_self(self, 1) { + self.bump(); + SelfKind::Region(None, Mutability::Immutable) + } else if self.is_keyword_ahead(1, &[kw::Mut]) && + isolated_self(self, 2) { + self.bump(); + self.bump(); + SelfKind::Region(None, Mutability::Mutable) + } else if self.look_ahead(1, |t| t.is_lifetime()) && + isolated_self(self, 2) { + self.bump(); + let lt = self.expect_lifetime(); + SelfKind::Region(Some(lt), Mutability::Immutable) + } else if self.look_ahead(1, |t| t.is_lifetime()) && + self.is_keyword_ahead(2, &[kw::Mut]) && + isolated_self(self, 3) { + self.bump(); + let lt = self.expect_lifetime(); + self.bump(); + SelfKind::Region(Some(lt), Mutability::Mutable) + } else { + return Ok(None); + }, expect_ident(self), self.prev_span) + } + token::BinOp(token::Star) => { + // `*self` + // `*const self` + // `*mut self` + // `*not_self` + // Emit special error for `self` cases. + let msg = "cannot pass `self` by raw pointer"; + (if isolated_self(self, 1) { + self.bump(); + self.struct_span_err(self.token.span, msg) + .span_label(self.token.span, msg) + .emit(); + SelfKind::Value(Mutability::Immutable) + } else if self.look_ahead(1, |t| t.is_mutability()) && + isolated_self(self, 2) { + self.bump(); + self.bump(); + self.struct_span_err(self.token.span, msg) + .span_label(self.token.span, msg) + .emit(); + SelfKind::Value(Mutability::Immutable) + } else { + return Ok(None); + }, expect_ident(self), self.prev_span) + } + token::Ident(..) => { + if isolated_self(self, 0) { + // `self` + // `self: TYPE` + let eself_ident = expect_ident(self); + let eself_hi = self.prev_span; + (if self.eat(&token::Colon) { + let ty = self.parse_ty()?; + SelfKind::Explicit(ty, Mutability::Immutable) + } else { + SelfKind::Value(Mutability::Immutable) + }, eself_ident, eself_hi) + } else if self.token.is_keyword(kw::Mut) && + isolated_self(self, 1) { + // `mut self` + // `mut self: TYPE` + self.bump(); + let eself_ident = expect_ident(self); + let eself_hi = self.prev_span; + (if self.eat(&token::Colon) { + let ty = self.parse_ty()?; + SelfKind::Explicit(ty, Mutability::Mutable) + } else { + SelfKind::Value(Mutability::Mutable) + }, eself_ident, eself_hi) + } else { + return Ok(None); + } + } + _ => return Ok(None), + }; + + let eself = source_map::respan(eself_lo.to(eself_hi), eself); + Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident))) + } + + /// Returns the parsed optional self parameter with attributes and whether a self + /// shortcut was used. + fn parse_self_parameter_with_attrs(&mut self) -> PResult<'a, Option> { + let attrs = self.parse_outer_attributes()?; + let param_opt = self.parse_self_param()?; + Ok(param_opt.map(|mut param| { + param.attrs = attrs.into(); + param + })) + } + + /// 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_param_fn: F) -> PResult<'a, P> + where F: FnMut(&mut Parser<'a>) -> PResult<'a, Param>, + { + self.expect(&token::OpenDelim(token::Paren))?; + + // Parse optional self argument. + let self_param = self.parse_self_parameter_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_param) = self_param { + if self.check(&token::CloseDelim(token::Paren)) { + (vec![self_param], false) + } else if self.eat(&token::Comma) { + let mut fn_inputs = vec![self_param]; + let (mut input, _, recovered) = self.parse_seq_to_before_end( + &token::CloseDelim(token::Paren), sep, parse_param_fn)?; + fn_inputs.append(&mut input); + (fn_inputs, recovered) + } else { + match self.expect_one_of(&[], &[]) { + Err(err) => return Err(err), + Ok(recovered) => (vec![self_param], recovered), + } + } + } else { + let (input, _, recovered) = + self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), + sep, + parse_param_fn)?; + (input, recovered) + }; + + if !recovered { + // Parse closing paren and return type. + self.expect(&token::CloseDelim(token::Paren))?; + } + // Replace duplicated recovered params with `_` pattern to avoid unecessary errors. + self.deduplicate_recovered_params_names(&mut fn_inputs); + + Ok(P(FnDecl { + inputs: fn_inputs, + output: self.parse_ret_ty(true)?, + c_variadic: false + })) } fn is_crate_vis(&self) -> bool { @@ -1122,7 +1433,6 @@ impl<'a> Parser<'a> { self.expected_tokens.push(TokenType::Keyword(kw::Crate)); if self.is_crate_vis() { self.bump(); // `crate` - self.sess.gated_spans.crate_visibility_modifier.borrow_mut().push(self.prev_span); return Ok(respan(self.prev_span, VisibilityKind::Crate(CrateSugar::JustCrate))); } @@ -1139,81 +1449,66 @@ impl<'a> Parser<'a> { // `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`. // Because of this, we only `bump` the `(` if we're assured it is appropriate to do so // by the following tokens. - if self.is_keyword_ahead(1, &[kw::Crate]) - && self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)` + if self.is_keyword_ahead(1, &[kw::Crate]) && + self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)` { - // Parse `pub(crate)`. + // `pub(crate)` self.bump(); // `(` self.bump(); // `crate` self.expect(&token::CloseDelim(token::Paren))?; // `)` - let vis = VisibilityKind::Crate(CrateSugar::PubCrate); - return Ok(respan(lo.to(self.prev_span), vis)); + let vis = respan( + lo.to(self.prev_span), + VisibilityKind::Crate(CrateSugar::PubCrate), + ); + return Ok(vis) } else if self.is_keyword_ahead(1, &[kw::In]) { - // Parse `pub(in path)`. + // `pub(in path)` self.bump(); // `(` self.bump(); // `in` let path = self.parse_path(PathStyle::Mod)?; // `path` self.expect(&token::CloseDelim(token::Paren))?; // `)` - let vis = VisibilityKind::Restricted { + let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted { path: P(path), id: ast::DUMMY_NODE_ID, - }; - return Ok(respan(lo.to(self.prev_span), vis)); - } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) - && self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower]) + }); + return Ok(vis) + } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) && + self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower]) { - // Parse `pub(self)` or `pub(super)`. + // `pub(self)` or `pub(super)` self.bump(); // `(` let path = self.parse_path(PathStyle::Mod)?; // `super`/`self` self.expect(&token::CloseDelim(token::Paren))?; // `)` - let vis = VisibilityKind::Restricted { + let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted { path: P(path), id: ast::DUMMY_NODE_ID, - }; - return Ok(respan(lo.to(self.prev_span), vis)); - } else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct. - self.recover_incorrect_vis_restriction()?; - // Emit diagnostic, but continue with public visibility. - } - } - - Ok(respan(lo, VisibilityKind::Public)) - } - - /// Recovery for e.g. `pub(something) fn ...` or `struct X { pub(something) y: Z }` - fn recover_incorrect_vis_restriction(&mut self) -> PResult<'a, ()> { - self.bump(); // `(` - let path = self.parse_path(PathStyle::Mod)?; - self.expect(&token::CloseDelim(token::Paren))?; // `)` - - let msg = "incorrect visibility restriction"; - let suggestion = r##"some possible visibility restrictions are: + }); + return Ok(vis) + } else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct + // `pub(something) fn ...` or `struct X { pub(something) y: Z }` + self.bump(); // `(` + let msg = "incorrect visibility restriction"; + let suggestion = r##"some possible visibility restrictions are: `pub(crate)`: visible only on the current crate `pub(super)`: visible only in the current module's parent `pub(in path::to::module)`: visible only on the specified path"##; - - let path_str = pprust::path_to_string(&path); - - struct_span_err!(self.sess.span_diagnostic, path.span, E0704, "{}", msg) - .help(suggestion) - .span_suggestion( - path.span, - &format!("make this visible only to module `{}` with `in`", path_str), - format!("in {}", path_str), - Applicability::MachineApplicable, - ) - .emit(); - - Ok(()) - } - - /// Parses `extern` followed by an optional ABI string, or nothing. - fn parse_extern_abi(&mut self) -> PResult<'a, Abi> { - if self.eat_keyword(kw::Extern) { - Ok(self.parse_opt_abi()?.unwrap_or(Abi::C)) - } else { - Ok(Abi::Rust) + let path = self.parse_path(PathStyle::Mod)?; + let sp = path.span; + let help_msg = format!("make this visible only to module `{}` with `in`", path); + self.expect(&token::CloseDelim(token::Paren))?; // `)` + struct_span_err!(self.sess.span_diagnostic, sp, E0704, "{}", msg) + .help(suggestion) + .span_suggestion( + sp, + &help_msg, + format!("in {}", path), + Applicability::MachineApplicable, + ) + .emit(); // Emit diagnostic, but continue with public visibility. + } } + + Ok(respan(lo, VisibilityKind::Public)) } /// Parses a string as an ABI spec on an extern type or module. Consumes @@ -1222,35 +1517,32 @@ impl<'a> Parser<'a> { match self.token.kind { token::Literal(token::Lit { kind: token::Str, symbol, suffix }) | token::Literal(token::Lit { kind: token::StrRaw(..), symbol, suffix }) => { - self.expect_no_suffix(self.token.span, "an ABI spec", suffix); + let sp = self.token.span; + self.expect_no_suffix(sp, "an ABI spec", suffix); self.bump(); match abi::lookup(&symbol.as_str()) { Some(abi) => Ok(Some(abi)), None => { - self.error_on_invalid_abi(symbol); + let prev_span = self.prev_span; + struct_span_err!( + self.sess.span_diagnostic, + prev_span, + E0703, + "invalid ABI: found `{}`", + symbol + ) + .span_label(prev_span, "invalid ABI") + .help(&format!("valid ABIs: {}", abi::all_names().join(", "))) + .emit(); Ok(None) } } } + _ => Ok(None), } } - /// Emit an error where `symbol` is an invalid ABI. - fn error_on_invalid_abi(&self, symbol: Symbol) { - let prev_span = self.prev_span; - struct_span_err!( - self.sess.span_diagnostic, - prev_span, - E0703, - "invalid ABI: found `{}`", - symbol - ) - .span_label(prev_span, "invalid ABI") - .help(&format!("valid ABIs: {}", abi::all_names().join(", "))) - .emit(); - } - /// We are parsing `async fn`. If we are on Rust 2015, emit an error. fn ban_async_in_2015(&self, async_span: Span) { if async_span.rust_2015() { @@ -1264,10 +1556,9 @@ impl<'a> Parser<'a> { } } - fn collect_tokens( - &mut self, - f: impl FnOnce(&mut Self) -> PResult<'a, R>, - ) -> PResult<'a, (R, TokenStream)> { + fn collect_tokens(&mut self, f: F) -> PResult<'a, (R, TokenStream)> + where F: FnOnce(&mut Self) -> PResult<'a, R> + { // Record all tokens we parse when parsing this item. let mut tokens = Vec::new(); let prev_collecting = match self.token_cursor.frame.last_token { @@ -1288,7 +1579,7 @@ impl<'a> Parser<'a> { // This can happen due to a bad interaction of two unrelated recovery mechanisms with // mismatched delimiters *and* recovery lookahead on the likely typo `pub ident(` // (#62881). - return Ok((ret?, TokenStream::default())); + return Ok((ret?, TokenStream::new(vec![]))); } else { &mut self.token_cursor.stack[prev].last_token }; @@ -1303,7 +1594,7 @@ impl<'a> Parser<'a> { // This can happen due to a bad interaction of two unrelated recovery mechanisms // with mismatched delimiters *and* recovery lookahead on the likely typo // `pub ident(` (#62895, different but similar to the case above). - return Ok((ret?, TokenStream::default())); + return Ok((ret?, TokenStream::new(vec![]))); } }; @@ -1341,7 +1632,7 @@ impl<'a> Parser<'a> { *t == token::BinOp(token::Star)) } - fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option)> { + pub fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option)> { let ret = match self.token.kind { token::Literal(token::Lit { kind: token::Str, symbol, suffix }) => (symbol, ast::StrStyle::Cooked, suffix), @@ -1368,6 +1659,25 @@ impl<'a> Parser<'a> { } } } + + fn report_invalid_macro_expansion_item(&self) { + self.struct_span_err( + self.prev_span, + "macros that expand to items must be delimited with braces or followed by a semicolon", + ).multipart_suggestion( + "change the delimiters to curly braces", + vec![ + (self.prev_span.with_hi(self.prev_span.lo() + BytePos(1)), String::from(" {")), + (self.prev_span.with_lo(self.prev_span.hi() - BytePos(1)), '}'.to_string()), + ], + Applicability::MaybeIncorrect, + ).span_suggestion( + self.sess.source_map.next_point(self.prev_span), + "add a semicolon", + ';'.to_string(), + Applicability::MaybeIncorrect, + ).emit(); + } } pub fn emit_unclosed_delims(unclosed_delims: &mut Vec, handler: &errors::Handler) { diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 97b1092452aaf..c776704b285aa 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1,18 +1,18 @@ -use super::{Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle, BlockMode}; -use super::{SemiColonMode, SeqSep, TokenExpectType}; +use super::{ + Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle, BlockMode, SemiColonMode, + SeqSep, TokenExpectType, +}; use super::pat::{GateOr, PARAM_EXPECTED}; -use super::diagnostics::Error; - -use crate::parse::literal::LitError; 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, Lit, + FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field, }; use crate::maybe_recover_from_interpolated_ty_qpath; use crate::parse::classify; -use crate::parse::token::{self, Token, TokenKind}; +use crate::parse::token::{self, Token}; +use crate::parse::diagnostics::Error; use crate::print::pprust; use crate::ptr::P; use crate::source_map::{self, Span}; @@ -20,7 +20,6 @@ use crate::symbol::{kw, sym}; use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par}; use errors::Applicability; -use syntax_pos::Symbol; use std::mem; use rustc_data_structures::thin_vec::ThinVec; @@ -239,9 +238,7 @@ impl<'a> Parser<'a> { self.bump(); if op.is_comparison() { - if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? { - return Ok(expr); - } + self.check_no_chained_comparison(&lhs, &op)?; } // Special cases: if op == AssocOp::As { @@ -252,7 +249,6 @@ impl<'a> Parser<'a> { self.last_type_ascription = Some((self.prev_span, maybe_path)); lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?; - self.sess.gated_spans.type_ascription.borrow_mut().push(lhs.span); continue } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq { // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to @@ -424,7 +420,7 @@ impl<'a> Parser<'a> { self.struct_span_err(span_of_tilde, "`~` cannot be used as a unary operator") .span_suggestion_short( span_of_tilde, - "use `!` to perform bitwise not", + "use `!` to perform bitwise negation", "!".to_owned(), Applicability::MachineApplicable ) @@ -454,9 +450,7 @@ impl<'a> Parser<'a> { self.bump(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; - let span = lo.to(span); - self.sess.gated_spans.box_syntax.borrow_mut().push(span); - (span, ExprKind::Box(e)) + (lo.to(span), ExprKind::Box(e)) } token::Ident(..) if self.token.is_ident_named(sym::not) => { // `not` is just an ordinary identifier in Rust-the-language, @@ -556,11 +550,8 @@ impl<'a> Parser<'a> { // Report non-fatal diagnostics, keep `x as usize` as an expression // in AST and continue parsing. - let msg = format!( - "`<` is interpreted as a start of generic arguments for `{}`, not a {}", - pprust::path_to_string(&path), - op_noun, - ); + let msg = format!("`<` is interpreted as a start of generic \ + arguments for `{}`, not a {}", path, op_noun); let span_after_type = parser_snapshot_after_type.token.span; let expr = mk_expr(self, P(Ty { span: path.span, @@ -1076,167 +1067,8 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } - /// Matches `lit = true | false | token_lit`. - pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> { - let mut recovered = None; - if self.token == token::Dot { - // Attempt to recover `.4` as `0.4`. - recovered = self.look_ahead(1, |next_token| { - if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) - = next_token.kind { - if self.token.span.hi() == next_token.span.lo() { - let s = String::from("0.") + &symbol.as_str(); - let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix); - return Some(Token::new(kind, self.token.span.to(next_token.span))); - } - } - None - }); - if let Some(token) = &recovered { - self.bump(); - self.struct_span_err(token.span, "float literals must have an integer part") - .span_suggestion( - token.span, - "must have an integer part", - pprust::token_to_string(token), - Applicability::MachineApplicable, - ) - .emit(); - } - } - - let token = recovered.as_ref().unwrap_or(&self.token); - match Lit::from_token(token) { - Ok(lit) => { - self.bump(); - Ok(lit) - } - Err(LitError::NotLiteral) => { - let msg = format!("unexpected token: {}", self.this_token_descr()); - Err(self.span_fatal(token.span, &msg)) - } - Err(err) => { - let (lit, span) = (token.expect_lit(), token.span); - self.bump(); - self.error_literal_from_token(err, lit, span); - // Pack possible quotes and prefixes from the original literal into - // the error literal's symbol so they can be pretty-printed faithfully. - let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); - let symbol = Symbol::intern(&suffixless_lit.to_string()); - let lit = token::Lit::new(token::Err, symbol, lit.suffix); - Lit::from_lit_token(lit, span).map_err(|_| unreachable!()) - } - } - } - - fn error_literal_from_token(&self, err: LitError, lit: token::Lit, span: Span) { - // Checks if `s` looks like i32 or u1234 etc. - fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { - s.len() > 1 - && s.starts_with(first_chars) - && s[1..].chars().all(|c| c.is_ascii_digit()) - } - - let token::Lit { kind, suffix, .. } = lit; - match err { - // `NotLiteral` is not an error by itself, so we don't report - // it and give the parser opportunity to try something else. - LitError::NotLiteral => {} - // `LexerError` *is* an error, but it was already reported - // by lexer, so here we don't report it the second time. - LitError::LexerError => {} - LitError::InvalidSuffix => { - self.expect_no_suffix( - span, - &format!("{} {} literal", kind.article(), kind.descr()), - suffix, - ); - } - LitError::InvalidIntSuffix => { - let suf = suffix.expect("suffix error with no suffix").as_str(); - if looks_like_width_suffix(&['i', 'u'], &suf) { - // If it looks like a width, try to be helpful. - let msg = format!("invalid width `{}` for integer literal", &suf[1..]); - self.struct_span_err(span, &msg) - .help("valid widths are 8, 16, 32, 64 and 128") - .emit(); - } else { - let msg = format!("invalid suffix `{}` for integer literal", suf); - self.struct_span_err(span, &msg) - .span_label(span, format!("invalid suffix `{}`", suf)) - .help("the suffix must be one of the integral types (`u32`, `isize`, etc)") - .emit(); - } - } - LitError::InvalidFloatSuffix => { - let suf = suffix.expect("suffix error with no suffix").as_str(); - if looks_like_width_suffix(&['f'], &suf) { - // If it looks like a width, try to be helpful. - let msg = format!("invalid width `{}` for float literal", &suf[1..]); - self.struct_span_err(span, &msg) - .help("valid widths are 32 and 64") - .emit(); - } else { - let msg = format!("invalid suffix `{}` for float literal", suf); - self.struct_span_err(span, &msg) - .span_label(span, format!("invalid suffix `{}`", suf)) - .help("valid suffixes are `f32` and `f64`") - .emit(); - } - } - LitError::NonDecimalFloat(base) => { - let descr = match base { - 16 => "hexadecimal", - 8 => "octal", - 2 => "binary", - _ => unreachable!(), - }; - self.struct_span_err(span, &format!("{} float literal is not supported", descr)) - .span_label(span, "not supported") - .emit(); - } - LitError::IntTooLarge => { - self.struct_span_err(span, "integer literal is too large") - .emit(); - } - } - } - - pub(super) fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option) { - if let Some(suf) = suffix { - let mut err = if kind == "a tuple index" - && [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suf) - { - // #59553: warn instead of reject out of hand to allow the fix to percolate - // through the ecosystem when people fix their macros - let mut err = self.sess.span_diagnostic.struct_span_warn( - sp, - &format!("suffixes on {} are invalid", kind), - ); - err.note(&format!( - "`{}` is *temporarily* accepted on tuple index fields as it was \ - incorrectly accepted on stable for a few releases", - suf, - )); - err.help( - "on proc macros, you'll want to use `syn::Index::from` or \ - `proc_macro::Literal::*_unsuffixed` for code that will desugar \ - to tuple field access", - ); - err.note( - "for more context, see https://github.com/rust-lang/rust/issues/60210", - ); - err - } else { - self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind)) - }; - err.span_label(sp, format!("invalid suffix `{}`", suf)); - err.emit(); - } - } - /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). - pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { + crate fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { maybe_whole_expr!(self); let minus_lo = self.token.span; @@ -1256,17 +1088,13 @@ impl<'a> Parser<'a> { } /// Parses a block or unsafe block. - pub(super) fn parse_block_expr( + crate fn parse_block_expr( &mut self, opt_label: Option::Y]; | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` + | + = help: consider adding a `where A: Foo` bound 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 f6c8e99e27a81..30fa9891a13e1 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 @@ -4,10 +4,10 @@ error[E0277]: the trait bound `A: Foo` is not satisfied LL | const Y: usize; | --------------- required by `Foo::Y` ... -LL | pub fn test() { - | -- help: consider further restricting this bound: `A: Foo +` LL | let _array: [u32; ::Y]; | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` + | + = help: consider adding a `where A: Foo` bound error: aborting due to previous error diff --git a/src/test/ui/associated-const/issue-63496.rs b/src/test/ui/associated-const/issue-63496.rs deleted file mode 100644 index 311c48b5e48c5..0000000000000 --- a/src/test/ui/associated-const/issue-63496.rs +++ /dev/null @@ -1,9 +0,0 @@ -trait A { - const C: usize; - - fn f() -> ([u8; A::C], [u8; A::C]); - //~^ ERROR: type annotations needed: cannot resolve - //~| ERROR: type annotations needed: cannot resolve -} - -fn main() {} diff --git a/src/test/ui/associated-const/issue-63496.stderr b/src/test/ui/associated-const/issue-63496.stderr deleted file mode 100644 index 70bb12de1fb72..0000000000000 --- a/src/test/ui/associated-const/issue-63496.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0283]: type annotations needed: cannot resolve `_: A` - --> $DIR/issue-63496.rs:4:21 - | -LL | const C: usize; - | --------------- required by `A::C` -LL | -LL | fn f() -> ([u8; A::C], [u8; A::C]); - | ^^^^ - -error[E0283]: type annotations needed: cannot resolve `_: A` - --> $DIR/issue-63496.rs:4:33 - | -LL | const C: usize; - | --------------- required by `A::C` -LL | -LL | fn f() -> ([u8; A::C], [u8; A::C]); - | ^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/associated-item/issue-48027.rs b/src/test/ui/associated-item/issue-48027.rs deleted file mode 100644 index c9b4ccd3e8a99..0000000000000 --- a/src/test/ui/associated-item/issue-48027.rs +++ /dev/null @@ -1,8 +0,0 @@ -trait Bar { - const X: usize; - fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: type annotations needed -} - -impl dyn Bar {} //~ ERROR: the trait `Bar` cannot be made into an object - -fn main() {} diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr deleted file mode 100644 index 562146a426d23..0000000000000 --- a/src/test/ui/associated-item/issue-48027.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-48027.rs:6:6 - | -LL | const X: usize; - | - the trait cannot contain associated consts like `X` -... -LL | impl dyn Bar {} - | ^^^^^^^ the trait `Bar` cannot be made into an object - -error[E0283]: type annotations needed: cannot resolve `_: Bar` - --> $DIR/issue-48027.rs:3:32 - | -LL | const X: usize; - | --------------- required by `Bar::X` -LL | fn return_n(&self) -> [u8; Bar::X]; - | ^^^^^^ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0038, E0283. -For more information about an error, try `rustc --explain E0038`. 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 9f6a73cfe3910..06e8230aa1589 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 @@ -9,10 +9,7 @@ LL | impl Case1 for S1 { error[E0277]: `<::C as std::iter::Iterator>::Item` is not an iterator --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 | -LL | fn assume_case1() { - | ^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::iter::Iterator` - | _| - | | +LL | / fn assume_case1() { LL | | LL | | LL | | @@ -22,6 +19,7 @@ LL | | } | |_^ `<::C as std::iter::Iterator>::Item` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `<::C as std::iter::Iterator>::Item` + = help: consider adding a `where <::C as std::iter::Iterator>::Item: std::iter::Iterator` bound error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 @@ -29,10 +27,7 @@ error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be sent be LL | trait Case1 { | ----------- required by `Case1` ... -LL | fn assume_case1() { - | ^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::marker::Send` - | _| - | | +LL | / fn assume_case1() { LL | | LL | | LL | | @@ -42,6 +37,7 @@ LL | | } | |_^ `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely | = 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 error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 @@ -49,10 +45,7 @@ error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be shared LL | trait Case1 { | ----------- required by `Case1` ... -LL | fn assume_case1() { - | ^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::marker::Sync` - | _| - | | +LL | / fn assume_case1() { LL | | LL | | LL | | @@ -62,6 +55,7 @@ LL | | } | |_^ `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely | = 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 error[E0277]: `<_ as Lam<&'a u8>>::App` doesn't implement `std::fmt::Debug` --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 diff --git a/src/test/ui/associated-type-bounds/union-bounds.rs b/src/test/ui/associated-type-bounds/union-bounds.rs index 97c5acf1f72ca..ce482fff401c8 100644 --- a/src/test/ui/associated-type-bounds/union-bounds.rs +++ b/src/test/ui/associated-type-bounds/union-bounds.rs @@ -3,13 +3,13 @@ #![feature(associated_type_bounds)] #![feature(untagged_unions)] -#![allow(unused_assignments)] +#![allow(unions_with_drop_fields, unused_assignments)] -trait Tr1: Copy { type As1: Copy; } -trait Tr2: Copy { type As2: Copy; } -trait Tr3: Copy { type As3: Copy; } -trait Tr4<'a>: Copy { type As4: Copy; } -trait Tr5: Copy { type As5: Copy; } +trait Tr1 { type As1; } +trait Tr2 { type As2; } +trait Tr3 { type As3; } +trait Tr4<'a> { type As4; } +trait Tr5 { type As5; } impl Tr1 for &str { type As1 = bool; } impl Tr2 for bool { type As2 = u8; } @@ -71,8 +71,7 @@ where let _: &'a T = &x.f0; } -#[derive(Copy, Clone)] -union UnSelf where Self: Tr1, T: Copy { +union UnSelf where Self: Tr1 { f0: T, f1: ::As1, f2: <::As1 as Tr2>::As2, diff --git a/src/test/ui/associated-types/associated-types-bound-failure.fixed b/src/test/ui/associated-types/associated-types-bound-failure.fixed deleted file mode 100644 index cc47f31d00456..0000000000000 --- a/src/test/ui/associated-types/associated-types-bound-failure.fixed +++ /dev/null @@ -1,29 +0,0 @@ -// run-rustfix -// Test equality constraints on associated types in a where clause. -#![allow(dead_code)] - -pub trait ToInt { - fn to_int(&self) -> isize; -} - -pub trait GetToInt -{ - type R; - - fn get(&self) -> ::R; -} - -fn foo(g: G) -> isize - where G : GetToInt, ::R: ToInt -{ - ToInt::to_int(&g.get()) //~ ERROR E0277 -} - -fn bar(g: G) -> isize - where G::R : ToInt -{ - ToInt::to_int(&g.get()) // OK -} - -pub fn main() { -} diff --git a/src/test/ui/associated-types/associated-types-bound-failure.rs b/src/test/ui/associated-types/associated-types-bound-failure.rs index 31e073cc7a8bd..883ac363b44e5 100644 --- a/src/test/ui/associated-types/associated-types-bound-failure.rs +++ b/src/test/ui/associated-types/associated-types-bound-failure.rs @@ -1,6 +1,4 @@ -// run-rustfix // Test equality constraints on associated types in a where clause. -#![allow(dead_code)] pub trait ToInt { fn to_int(&self) -> isize; 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 c420c86a2758f..85acf134d51d5 100644 --- a/src/test/ui/associated-types/associated-types-bound-failure.stderr +++ b/src/test/ui/associated-types/associated-types-bound-failure.stderr @@ -1,14 +1,13 @@ error[E0277]: the trait bound `::R: ToInt` is not satisfied - --> $DIR/associated-types-bound-failure.rs:19:19 + --> $DIR/associated-types-bound-failure.rs:17:19 | LL | fn to_int(&self) -> isize; | -------------------------- required by `ToInt::to_int` ... -LL | where G : GetToInt - | - help: consider further restricting the associated type: `, ::R: ToInt` -LL | { LL | ToInt::to_int(&g.get()) | ^^^^^^^^ the trait `ToInt` is not implemented for `::R` + | + = help: consider adding a `where ::R: ToInt` bound error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed b/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed deleted file mode 100644 index aa23326506f63..0000000000000 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed +++ /dev/null @@ -1,15 +0,0 @@ -// run-rustfix -#![allow(unused_variables)] - -trait Get { - type Value; - fn get(&self) -> ::Value; -} - -trait Other { - fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} - //~^ ERROR the trait bound `Self: Get` is not satisfied -} - -fn main() { -} diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.rs b/src/test/ui/associated-types/associated-types-for-unimpl-trait.rs index 0f6cea8e69fcf..5b10d1dc2fdb5 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.rs +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.rs @@ -1,6 +1,3 @@ -// run-rustfix -#![allow(unused_variables)] - trait Get { type Value; fn get(&self) -> ::Value; diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr index 83d5390417e77..9f033687a0072 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -1,11 +1,10 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-for-unimpl-trait.rs:10:5 + --> $DIR/associated-types-for-unimpl-trait.rs:7:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ - | | | - | | help: consider further restricting `Self`: `where Self: Get` - | the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | + = help: consider adding a `where Self: Get` bound error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr b/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr index 0b8b7fab1359f..01f66a18d25bd 100644 --- a/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr +++ b/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr @@ -1,10 +1,10 @@ error[E0277]: the trait bound `T: Foo` is not satisfied --> $DIR/associated-types-invalid-trait-ref-issue-18865.rs:10:12 | -LL | fn f>(t: &T) { - | -- help: consider further restricting this bound: `T: Foo +` LL | let u: >::Bar = t.get_bar(); | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T` + | + = help: consider adding a `where T: Foo` bound error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr index 78198322913c7..ada9cacbee523 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr @@ -2,10 +2,9 @@ error[E0277]: the trait bound `T: Get` is not satisfied --> $DIR/associated-types-no-suitable-bound.rs:11:5 | LL | fn uhoh(foo: ::Value) {} - | ^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | help: consider restricting this bound: `T: Get` - | the trait `Get` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` + | + = help: consider adding a `where T: Get` bound error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr index 6aa0403088d3c..56cd6d09caddc 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr @@ -2,10 +2,9 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ - | | | - | | help: consider further restricting `Self`: `where Self: Get` - | the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | + = help: consider adding a `where Self: Get` bound error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr index 8c242be979611..71175d36f645f 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr @@ -2,10 +2,9 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-no-suitable-supertrait.rs:17:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ - | | | - | | help: consider further restricting `Self`: `where Self: Get` - | the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | + = help: consider adding a `where Self: Get` bound error[E0277]: the trait bound `(T, U): Get` is not satisfied --> $DIR/associated-types-no-suitable-supertrait.rs:22:5 diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed deleted file mode 100644 index f357045a456e6..0000000000000 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed +++ /dev/null @@ -1,30 +0,0 @@ -// run-rustfix -// Check that we get an error when you use `::Value` in -// the trait definition even if there is no default method. - -trait Get { - type Value; -} - -trait Other { - fn okay(&self, foo: U, bar: ::Value) where Self: Get ; - //~^ ERROR E0277 -} - -impl Get for () { - type Value = f32; -} - -impl Get for f64 { - type Value = u32; -} - -impl Other for () { - fn okay(&self, _foo: U, _bar: ::Value) { } -} - -impl Other for f64 { - fn okay(&self, _foo: U, _bar: ::Value) { } -} - -fn main() { } diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs index 549fc8fc618e0..fc38b26f50b62 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs @@ -1,4 +1,3 @@ -// run-rustfix // Check that we get an error when you use `::Value` in // the trait definition even if there is no default method. diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index cb01488fa34d4..a260e37918254 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -1,11 +1,10 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:5 + --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:9:5 | LL | fn okay(&self, foo: U, bar: ::Value); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | | - | | help: consider further restricting `Self`: `where Self: Get` - | the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | + = help: consider adding a `where Self: Get` bound error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-unsized.fixed b/src/test/ui/associated-types/associated-types-unsized.fixed deleted file mode 100644 index f780d171fee8e..0000000000000 --- a/src/test/ui/associated-types/associated-types-unsized.fixed +++ /dev/null @@ -1,14 +0,0 @@ -// run-rustfix -#![allow(dead_code, unused_variables)] - -trait Get { - type Value: ?Sized; - fn get(&self) -> ::Value; -} - -fn foo(t: T) where ::Value: std::marker::Sized { - let x = t.get(); //~ ERROR the size for values of type -} - -fn main() { -} diff --git a/src/test/ui/associated-types/associated-types-unsized.rs b/src/test/ui/associated-types/associated-types-unsized.rs index bdba4c7ff16a1..a9bc24e44d165 100644 --- a/src/test/ui/associated-types/associated-types-unsized.rs +++ b/src/test/ui/associated-types/associated-types-unsized.rs @@ -1,6 +1,3 @@ -// run-rustfix -#![allow(dead_code, unused_variables)] - trait Get { type Value: ?Sized; fn get(&self) -> ::Value; diff --git a/src/test/ui/associated-types/associated-types-unsized.stderr b/src/test/ui/associated-types/associated-types-unsized.stderr index 2352ac4ad3822..b5db9743932e9 100644 --- a/src/test/ui/associated-types/associated-types-unsized.stderr +++ b/src/test/ui/associated-types/associated-types-unsized.stderr @@ -1,13 +1,12 @@ error[E0277]: the size for values of type `::Value` cannot be known at compilation time - --> $DIR/associated-types-unsized.rs:10:9 + --> $DIR/associated-types-unsized.rs:7:9 | -LL | fn foo(t: T) { - | - help: consider further restricting the associated type: `where ::Value: std::marker::Sized` LL | let x = t.get(); | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `::Value` = note: to learn more, visit + = help: consider adding a `where ::Value: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr index 5ea98dcd4a972..15bebce47dd6a 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | bar(foo, x) | ^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 37:8... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 37:8... --> $DIR/project-fn-ret-contravariant.rs:37:8 | LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 { @@ -23,4 +23,3 @@ LL | bar(foo, x) error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index 627609c4a9c00..62b4cb10911fb 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | bar(foo, x) | ^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 44:8... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 44:8... --> $DIR/project-fn-ret-invariant.rs:44:8 | LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { @@ -19,4 +19,3 @@ LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/associated-types/issue-44153.rs b/src/test/ui/associated-types/issue-44153.rs deleted file mode 100644 index 2101cb61a94d1..0000000000000 --- a/src/test/ui/associated-types/issue-44153.rs +++ /dev/null @@ -1,19 +0,0 @@ -pub trait Array { - type Element; -} - -pub trait Visit { - fn visit() {} -} - -impl Array for () { - type Element = (); -} - -impl<'a> Visit for () where - (): Array, -{} - -fn main() { - <() as Visit>::visit(); //~ ERROR: type mismatch resolving -} diff --git a/src/test/ui/associated-types/issue-44153.stderr b/src/test/ui/associated-types/issue-44153.stderr deleted file mode 100644 index b62a866a20be3..0000000000000 --- a/src/test/ui/associated-types/issue-44153.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0271]: type mismatch resolving `<() as Array>::Element == &()` - --> $DIR/issue-44153.rs:18: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 `()` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/issue-48010.rs b/src/test/ui/associated-types/issue-48010.rs deleted file mode 100644 index 70e30c132d05c..0000000000000 --- a/src/test/ui/associated-types/issue-48010.rs +++ /dev/null @@ -1,23 +0,0 @@ -// check-pass - -#![crate_type = "lib"] - -pub struct Foo; - -pub struct Path { - _inner: T::Slice, -} - -pub trait Bar: Sized { - type Slice: ?Sized; - - fn open(_: &Path); -} - -impl Bar for Foo { - type Slice = [u8]; - - fn open(_: &Path) { - unimplemented!() - } -} diff --git a/src/test/ui/associated-types/issue-64855-2.rs b/src/test/ui/associated-types/issue-64855-2.rs deleted file mode 100644 index 1d53bd5703165..0000000000000 --- a/src/test/ui/associated-types/issue-64855-2.rs +++ /dev/null @@ -1,5 +0,0 @@ -// check-pass - -pub struct Bar<'a>(&'a Self) where Self: ; - -fn main() {} diff --git a/src/test/ui/associated-types/issue-64855.rs b/src/test/ui/associated-types/issue-64855.rs deleted file mode 100644 index 81cf3ae6e83b6..0000000000000 --- a/src/test/ui/associated-types/issue-64855.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub trait Foo { - type Type; -} - -pub struct Bar(::Type) where Self: ; -//~^ ERROR the trait bound `Bar: Foo` is not satisfied - -fn main() {} diff --git a/src/test/ui/associated-types/issue-64855.stderr b/src/test/ui/associated-types/issue-64855.stderr deleted file mode 100644 index 6ad795c11176d..0000000000000 --- a/src/test/ui/associated-types/issue-64855.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0277]: the trait bound `Bar: Foo` is not satisfied - --> $DIR/issue-64855.rs:5:19 - | -LL | pub struct Bar(::Type) where Self: ; - | ^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bar` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index 64c9f69311582..563885133a4c1 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"kind":{"variant":"ExternCrate","fields":[null]},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"span":{"lo":0,"hi":0},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}} +{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"kind":{"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/async-assoc-fn-anon-lifetimes.rs b/src/test/ui/async-await/async-assoc-fn-anon-lifetimes.rs deleted file mode 100644 index 8e08b82b9d3e3..0000000000000 --- a/src/test/ui/async-await/async-assoc-fn-anon-lifetimes.rs +++ /dev/null @@ -1,23 +0,0 @@ -// 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-block-control-flow-static-semantics.rs b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs index 971d447633481..753a4e491550f 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 @@ -20,7 +20,7 @@ fn return_targets_async_block_not_fn() -> u8 { } async fn return_targets_async_block_not_async_fn() -> u8 { - //~^ ERROR mismatched types + //~^ ERROR type mismatch resolving let block = async { return 0u8; }; 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 a9b0e7ae7795d..c36caa5586fb0 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 @@ -39,22 +39,6 @@ LL | let _: &dyn Future = █ found type `()` = note: required for the cast to the object type `dyn std::future::Future` -error[E0308]: mismatched types - --> $DIR/async-block-control-flow-static-semantics.rs:22:58 - | -LL | async fn return_targets_async_block_not_async_fn() -> u8 { - | __________________________________________________________^ -LL | | -LL | | let block = async { -LL | | return 0u8; -... | -LL | | -LL | | } - | |_^ expected u8, found () - | - = note: expected type `u8` - found type `()` - error[E0271]: type mismatch resolving `::Output == ()` --> $DIR/async-block-control-flow-static-semantics.rs:27:39 | @@ -65,6 +49,16 @@ LL | let _: &dyn Future = █ found type `()` = 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:22:55 + | +LL | async fn return_targets_async_block_not_async_fn() -> u8 { + | ^^ expected (), found u8 + | + = note: expected type `()` + found type `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:48:44 | diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed b/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed deleted file mode 100644 index f004b4180ddc9..0000000000000 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed +++ /dev/null @@ -1,12 +0,0 @@ -// edition:2018 -// run-rustfix - -fn foo() -> Box> { - let x = 0u32; - Box::new(async move { x } ) - //~^ ERROR E0373 -} - -fn main() { - let _foo = foo(); -} diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.rs b/src/test/ui/async-await/async-borrowck-escaping-block-error.rs deleted file mode 100644 index 4f35fd52ca39b..0000000000000 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.rs +++ /dev/null @@ -1,12 +0,0 @@ -// edition:2018 -// run-rustfix - -fn foo() -> Box> { - let x = 0u32; - Box::new(async { x } ) - //~^ ERROR E0373 -} - -fn main() { - let _foo = foo(); -} diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr deleted file mode 100644 index 0eb3971d14a38..0000000000000 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function - --> $DIR/async-borrowck-escaping-block-error.rs:6:20 - | -LL | Box::new(async { x } ) - | ^^-^^ - | | | - | | `x` is borrowed here - | may outlive borrowed value `x` - | -note: generator is returned here - --> $DIR/async-borrowck-escaping-block-error.rs:4:13 - | -LL | fn foo() -> Box> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: to force the async block 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-borrowck-escaping-closure-error.polonius.stderr b/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr new file mode 100644 index 0000000000000..5f20367b6aba9 --- /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-error-span.rs b/src/test/ui/async-await/async-error-span.rs index 28132c9789c67..dec3ac0f68554 100644 --- a/src/test/ui/async-await/async-error-span.rs +++ b/src/test/ui/async-await/async-error-span.rs @@ -9,7 +9,7 @@ fn get_future() -> impl Future { } async fn foo() { - let a; //~ ERROR type inside `async fn` body must be known in this context + let a; //~ ERROR type inside `async` object must be known in this context get_future().await; } diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr index b551b99587dd9..47441f5e4efce 100644 --- a/src/test/ui/async-await/async-error-span.stderr +++ b/src/test/ui/async-await/async-error-span.stderr @@ -1,10 +1,10 @@ -error[E0698]: type inside `async fn` body must be known in this context +error[E0698]: type inside `async` object must be known in this context --> $DIR/async-error-span.rs:12:9 | LL | let a; | ^ cannot infer type | -note: the type is part of the `async fn` body because of this `await` +note: the type is part of the `async` object because of this `await` --> $DIR/async-error-span.rs:13:5 | LL | get_future().await; diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 696bd5c39d283..001e0b1cad305 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -9,9 +9,9 @@ LL | assert_send(local_dropped_before_await()); | = 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, 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::fmt::Debug, fn() -> impl std::future::Future {fut}, 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, ()}]` + = 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, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` @@ -26,9 +26,9 @@ LL | assert_send(non_send_temporary_in_match()); | = 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, 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 `{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, ()}` + = 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, ()}]` + = 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, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` @@ -45,9 +45,9 @@ 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, 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 `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, fn() -> impl std::future::Future {fut}, 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, fn() -> impl std::future::Future {fut}, 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, fn() -> impl std::future::Future {fut}, 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` @@ -68,9 +68,9 @@ 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, 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 `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, fn() -> impl std::future::Future {fut}, 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, fn() -> impl std::future::Future {fut}, 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, fn() -> impl std::future::Future {fut}, 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` 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 4a413381aa300..3ffcbb58595eb 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 @@ -7,7 +7,7 @@ // // See issue #59123 for a full explanation. -// ignore-emscripten (sizes don't match) +// ignore-wasm32-bare (sizes don't match) // run-pass // edition:2018 @@ -22,8 +22,7 @@ struct BigFut([u8; BIG_FUT_SIZE]); impl BigFut { fn new() -> Self { BigFut([0; BIG_FUT_SIZE]) - } -} + } } impl Drop for BigFut { fn drop(&mut self) {} diff --git a/src/test/ui/async-await/async-fn-size-uninit-locals.rs b/src/test/ui/async-await/async-fn-size-uninit-locals.rs deleted file mode 100644 index 0558084f4f8a3..0000000000000 --- a/src/test/ui/async-await/async-fn-size-uninit-locals.rs +++ /dev/null @@ -1,103 +0,0 @@ -// Test that we don't store uninitialized locals in futures from `async fn`. -// -// The exact sizes can change by a few bytes (we'd like to know when they do). -// What we don't want to see is the wrong multiple of 1024 (the size of `Big`) -// being reflected in the size. - -// ignore-emscripten (sizes don't match) -// run-pass - -// edition:2018 - -#![allow(unused_variables, unused_assignments)] - -use std::future::Future; -use std::pin::Pin; -use std::task::{Context, Poll}; - -const BIG_FUT_SIZE: usize = 1024; -struct Big([u8; BIG_FUT_SIZE]); - -impl Big { - fn new() -> Self { - Big([0; BIG_FUT_SIZE]) - } -} - -impl Drop for Big { - fn drop(&mut self) {} -} - -#[allow(dead_code)] -struct Joiner { - a: Option, - b: Option, - c: Option, -} - -impl Future for Joiner { - type Output = (); - - fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll { - Poll::Ready(()) - } -} - -fn noop() {} -async fn fut() {} - -async fn single() { - let x; - fut().await; - x = Big::new(); -} - -async fn single_with_noop() { - let x; - fut().await; - noop(); - x = Big::new(); - noop(); -} - -async fn joined() { - let joiner; - let a = Big::new(); - let b = Big::new(); - let c = Big::new(); - - fut().await; - noop(); - joiner = Joiner { a: Some(a), b: Some(b), c: Some(c) }; - noop(); -} - -async fn joined_with_noop() { - let joiner; - let a = Big::new(); - let b = Big::new(); - let c = Big::new(); - - fut().await; - noop(); - joiner = Joiner { a: Some(a), b: Some(b), c: Some(c) }; - noop(); -} - -async fn join_retval() -> Joiner { - let a = Big::new(); - let b = Big::new(); - let c = Big::new(); - - fut().await; - noop(); - Joiner { a: Some(a), b: Some(b), c: Some(c) } -} - -fn main() { - assert_eq!(8, std::mem::size_of_val(&single())); - assert_eq!(12, std::mem::size_of_val(&single_with_noop())); - assert_eq!(3084, std::mem::size_of_val(&joined())); - assert_eq!(3084, std::mem::size_of_val(&joined_with_noop())); - assert_eq!(3080, std::mem::size_of_val(&join_retval())); -} diff --git a/src/test/ui/async-await/async-fn-size.rs b/src/test/ui/async-await/async-fn-size.rs index b313992db4ecb..b5c94ecb71690 100644 --- a/src/test/ui/async-await/async-fn-size.rs +++ b/src/test/ui/async-await/async-fn-size.rs @@ -89,10 +89,10 @@ fn main() { assert_eq!(8, std::mem::size_of_val(&await1_level1())); assert_eq!(12, std::mem::size_of_val(&await2_level1())); assert_eq!(12, std::mem::size_of_val(&await3_level1())); - assert_eq!(24, std::mem::size_of_val(&await3_level2())); - assert_eq!(36, std::mem::size_of_val(&await3_level3())); - assert_eq!(48, std::mem::size_of_val(&await3_level4())); - assert_eq!(60, std::mem::size_of_val(&await3_level5())); + assert_eq!(20, std::mem::size_of_val(&await3_level2())); + assert_eq!(28, std::mem::size_of_val(&await3_level3())); + assert_eq!(36, std::mem::size_of_val(&await3_level4())); + assert_eq!(44, std::mem::size_of_val(&await3_level5())); assert_eq!(1, wait(base())); assert_eq!(1, wait(await1_level1())); 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 4b5e2d59e38c9..7caa9f26bc2f8 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 @@ -244,5 +244,4 @@ LL | let _ = await bar()?; error: aborting due to 35 previous errors -Some errors have detailed explanations: E0277, E0728. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. 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 7633825eb32ab..d3f88af09d134 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 @@ -10,18 +10,18 @@ error[E0670]: `async fn` is not permitted in the 2015 edition LL | fn baz() { async fn foo() {} } | ^^^^^ -error[E0670]: `async fn` is not permitted in the 2015 edition - --> $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:8:5 | LL | async fn bar() {} | ^^^^^ +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $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:14:5 | diff --git a/src/test/ui/async-await/issue-60709.rs b/src/test/ui/async-await/issue-60709.rs index 61f6ed1b7b2ce..9ee419c4a56fb 100644 --- a/src/test/ui/async-await/issue-60709.rs +++ b/src/test/ui/async-await/issue-60709.rs @@ -3,7 +3,6 @@ // compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018 // run-pass -// ignore-asmjs wasm2js does not support source maps yet use std::future::Future; use std::task::Poll; 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 deleted file mode 100644 index 1936d1a2ed56e..0000000000000 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.rs +++ /dev/null @@ -1,25 +0,0 @@ -// 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 deleted file mode 100644 index 9e9fc52e30b7f..0000000000000 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ /dev/null @@ -1,23 +0,0 @@ -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/issues/issue-51719.stderr b/src/test/ui/async-await/issues/issue-51719.stderr index 5b9adb253d968..6c3c8889da7ce 100644 --- a/src/test/ui/async-await/issues/issue-51719.stderr +++ b/src/test/ui/async-await/issues/issue-51719.stderr @@ -8,4 +8,3 @@ LL | let _gen = || foo().await; error: aborting due to previous error -For more information about this error, try `rustc --explain E0728`. diff --git a/src/test/ui/async-await/issues/issue-51751.stderr b/src/test/ui/async-await/issues/issue-51751.stderr index f120bd119c540..e50c78534f852 100644 --- a/src/test/ui/async-await/issues/issue-51751.stderr +++ b/src/test/ui/async-await/issues/issue-51751.stderr @@ -9,4 +9,3 @@ LL | let finished = result.await; error: aborting due to previous error -For more information about this error, try `rustc --explain E0728`. 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 538430290d299..f63eaa4c48a97 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -40,5 +40,4 @@ LL | F: Future error: aborting due to 4 previous errors -Some errors have detailed explanations: E0277, E0728. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issues/issue-62009-2.stderr b/src/test/ui/async-await/issues/issue-62009-2.stderr index 47b74b5574fea..79b6803263eec 100644 --- a/src/test/ui/async-await/issues/issue-62009-2.stderr +++ b/src/test/ui/async-await/issues/issue-62009-2.stderr @@ -8,4 +8,3 @@ LL | (async || 2333)().await; error: aborting due to previous error -For more information about this error, try `rustc --explain E0728`. diff --git a/src/test/ui/async-await/issues/issue-63388-1.rs b/src/test/ui/async-await/issues/issue-63388-1.rs index baecf49c798e2..3cde5de219880 100644 --- a/src/test/ui/async-await/issues/issue-63388-1.rs +++ b/src/test/ui/async-await/issues/issue-63388-1.rs @@ -9,9 +9,9 @@ trait Foo {} impl Xyz { async fn do_sth<'a>( &'a self, foo: &dyn Foo - ) -> &dyn Foo + ) -> &dyn Foo //~ ERROR lifetime mismatch { - foo //~ ERROR lifetime mismatch + foo } } diff --git a/src/test/ui/async-await/issues/issue-63388-1.stderr b/src/test/ui/async-await/issues/issue-63388-1.stderr index 2917fa9ccb7f2..a54cadb0cd251 100644 --- a/src/test/ui/async-await/issues/issue-63388-1.stderr +++ b/src/test/ui/async-await/issues/issue-63388-1.stderr @@ -1,13 +1,12 @@ error[E0623]: lifetime mismatch - --> $DIR/issue-63388-1.rs:14:9 + --> $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 - | -------- -LL | { -LL | foo - | ^^^ ...but data from `foo` is returned here + | ^^^^^^^^ + | | + | ...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.stderr b/src/test/ui/async-await/issues/issue-63388-2.stderr index efec160588fc4..1edeb3d549389 100644 --- a/src/test/ui/async-await/issues/issue-63388-2.stderr +++ b/src/test/ui/async-await/issues/issue-63388-2.stderr @@ -11,19 +11,18 @@ error: cannot infer an appropriate lifetime | LL | foo: &dyn Foo, bar: &'a dyn Foo | ^^^ ...but this borrow... -... -LL | foo - | --- this return type evaluates to the `'static` lifetime... +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 +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 | 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 diff --git a/src/test/ui/async-await/issues/issue-64964.rs b/src/test/ui/async-await/issues/issue-64964.rs deleted file mode 100644 index 11f6cb6af9cc6..0000000000000 --- a/src/test/ui/async-await/issues/issue-64964.rs +++ /dev/null @@ -1,22 +0,0 @@ -// 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/issue-65159.rs b/src/test/ui/async-await/issues/issue-65159.rs deleted file mode 100644 index b5fee061f277e..0000000000000 --- a/src/test/ui/async-await/issues/issue-65159.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Regression test for #65159. We used to ICE. -// -// edition:2018 - -async fn copy() -> Result<()> //~ ERROR wrong number of type arguments -{ - Ok(()) -} - -fn main() { } diff --git a/src/test/ui/async-await/issues/issue-65159.stderr b/src/test/ui/async-await/issues/issue-65159.stderr deleted file mode 100644 index 56d2c38b302e9..0000000000000 --- a/src/test/ui/async-await/issues/issue-65159.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0107]: wrong number of type arguments: expected 2, found 1 - --> $DIR/issue-65159.rs:5:20 - | -LL | async fn copy() -> Result<()> - | ^^^^^^^^^^ expected 2 type arguments - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0107`. 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 index f826a86f08985..49ebf414c550b 100644 --- a/src/test/ui/async-await/issues/non-async-enclosing-span.stderr +++ b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr @@ -9,4 +9,3 @@ LL | let y = do_the_thing().await; error: aborting due to previous error -For more information about this error, try `rustc --explain E0728`. diff --git a/src/test/ui/async-await/return-ty-raw-ptr-coercion.rs b/src/test/ui/async-await/return-ty-raw-ptr-coercion.rs deleted file mode 100644 index 9fe0869cad6c0..0000000000000 --- a/src/test/ui/async-await/return-ty-raw-ptr-coercion.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Check that we apply unsizing coercions based on the return type. -// -// Also serves as a regression test for #60424. -// -// edition:2018 -// check-pass - -#![allow(warnings)] - -use std::fmt::Debug; - -const TMP: u32 = 22; - -// Coerce from `&u32` to `*const u32` -fn raw_pointer_coercion() { - fn sync_example() -> *const u32 { - &TMP - } - - async fn async_example() -> *const u32 { - &TMP - } -} - -fn main() {} diff --git a/src/test/ui/async-await/return-ty-unsize-coercion.rs b/src/test/ui/async-await/return-ty-unsize-coercion.rs deleted file mode 100644 index 93832ef7eddb5..0000000000000 --- a/src/test/ui/async-await/return-ty-unsize-coercion.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Check that we apply unsizing coercions based on the return type. -// -// Also serves as a regression test for #60424. -// -// edition:2018 -// check-pass - -#![allow(warnings)] - -use std::fmt::Debug; - -// Unsizing coercion from `Box<&'static str>` to `Box`. -fn unsize_trait_coercion() { - fn sync_example() -> Box { - Box::new("asdf") - } - - async fn async_example() -> Box { - Box::new("asdf") - } -} - -// Unsizing coercion from `Box<[u32; N]>` to `Box<[32]>`. -fn unsize_slice_coercion() { - fn sync_example() -> Box<[u32]> { - Box::new([0]) - } - - async fn async_example() -> Box<[u32]> { - Box::new([0]) - } -} - -// Unsizing coercion from `&[&str; 1]` to `&[&str]` -fn unsize_slice_str_coercion() { - fn sync_example() -> &'static [&'static str] { - &["hi"] - } - - async fn async_example() -> &'static [&'static str] { - &["hi"] - } -} - -fn main() {} diff --git a/src/test/ui/async-await/unreachable-lint-1.rs b/src/test/ui/async-await/unreachable-lint-1.rs deleted file mode 100644 index d63d643c4e70b..0000000000000 --- a/src/test/ui/async-await/unreachable-lint-1.rs +++ /dev/null @@ -1,12 +0,0 @@ -// 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 deleted file mode 100644 index 382581bf94554..0000000000000 --- a/src/test/ui/async-await/unreachable-lint-1.stderr +++ /dev/null @@ -1,16 +0,0 @@ -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 deleted file mode 100644 index ca18cfde4f2f5..0000000000000 --- a/src/test/ui/async-await/unreachable-lint.rs +++ /dev/null @@ -1,13 +0,0 @@ -// 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 2876f9fea0e00..d8ea87d2775bd 100644 --- a/src/test/ui/async-await/unresolved_type_param.rs +++ b/src/test/ui/async-await/unresolved_type_param.rs @@ -7,9 +7,9 @@ async fn bar() -> () {} async fn foo() { bar().await; - //~^ ERROR type inside `async fn` body must be known in this context + //~^ ERROR type inside `async` object must be known in this context //~| NOTE cannot infer type for `T` - //~| NOTE the type is part of the `async fn` body because of this `await` + //~| NOTE the type is part of the `async` object because of this `await` //~| NOTE in this expansion of desugaring of `await` } fn main() {} diff --git a/src/test/ui/async-await/unresolved_type_param.stderr b/src/test/ui/async-await/unresolved_type_param.stderr index c7866fc774415..f3090a2b980e8 100644 --- a/src/test/ui/async-await/unresolved_type_param.stderr +++ b/src/test/ui/async-await/unresolved_type_param.stderr @@ -1,10 +1,10 @@ -error[E0698]: type inside `async fn` body must be known in this context +error[E0698]: type inside `async` object must be known in this context --> $DIR/unresolved_type_param.rs:9:5 | LL | bar().await; | ^^^ cannot infer type for `T` | -note: the type is part of the `async fn` body because of this `await` +note: the type is part of the `async` object because of this `await` --> $DIR/unresolved_type_param.rs:9:5 | LL | bar().await; diff --git a/src/test/ui/async-await/unused-lifetime.rs b/src/test/ui/async-await/unused-lifetime.rs deleted file mode 100644 index 1cf546bcb4266..0000000000000 --- a/src/test/ui/async-await/unused-lifetime.rs +++ /dev/null @@ -1,42 +0,0 @@ -// edition:2018 - -// Avoid spurious warnings of unused lifetime. The below async functions -// are desugered to have an unused lifetime -// but we don't want to warn about that as there's nothing they can do about it. - -#![deny(unused_lifetimes)] -#![allow(dead_code)] - -pub async fn october(s: &str) { - println!("{}", s); -} - -pub async fn async_fn(&mut ref s: &mut[i32]) { - println!("{:?}", s); -} - -macro_rules! foo_macro { - () => { - pub async fn async_fn_in_macro(&mut ref _s: &mut[i32]) {} - }; -} - -foo_macro!(); - -pub async fn func_with_unused_lifetime<'a>(s: &'a str) { - //~^ ERROR lifetime parameter `'a` never used - println!("{}", s); -} - -pub async fn func_with_two_unused_lifetime<'a, 'b>(s: &'a str, t: &'b str) { - //~^ ERROR lifetime parameter `'a` never used - //~^^ ERROR lifetime parameter `'b` never used - println!("{}", s); -} - -pub async fn func_with_unused_lifetime_in_two_params<'c>(s: &'c str, t: &'c str) { - //~^ ERROR lifetime parameter `'c` never used - println!("{}", s); -} - -fn main() {} diff --git a/src/test/ui/async-await/unused-lifetime.stderr b/src/test/ui/async-await/unused-lifetime.stderr deleted file mode 100644 index 885cdc04cfa4c..0000000000000 --- a/src/test/ui/async-await/unused-lifetime.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error: lifetime parameter `'a` never used - --> $DIR/unused-lifetime.rs:26:40 - | -LL | pub async fn func_with_unused_lifetime<'a>(s: &'a str) { - | ^^ - | -note: lint level defined here - --> $DIR/unused-lifetime.rs:7:9 - | -LL | #![deny(unused_lifetimes)] - | ^^^^^^^^^^^^^^^^ - -error: lifetime parameter `'a` never used - --> $DIR/unused-lifetime.rs:31:44 - | -LL | pub async fn func_with_two_unused_lifetime<'a, 'b>(s: &'a str, t: &'b str) { - | ^^ - -error: lifetime parameter `'b` never used - --> $DIR/unused-lifetime.rs:31:48 - | -LL | pub async fn func_with_two_unused_lifetime<'a, 'b>(s: &'a str, t: &'b str) { - | ^^ - -error: lifetime parameter `'c` never used - --> $DIR/unused-lifetime.rs:37:54 - | -LL | pub async fn func_with_unused_lifetime_in_two_params<'c>(s: &'c str, t: &'c str) { - | ^^ - -error: aborting due to 4 previous errors - diff --git a/src/test/ui/auto-trait-validation.stderr b/src/test/ui/auto-trait-validation.stderr index 51422fab81fda..ae21984c06d72 100644 --- a/src/test/ui/auto-trait-validation.stderr +++ b/src/test/ui/auto-trait-validation.stderr @@ -18,5 +18,4 @@ LL | auto trait MyTrait { fn foo() {} } error: aborting due to 3 previous errors -Some errors have detailed explanations: E0380, E0567, E0568. -For more information about an error, try `rustc --explain E0380`. +For more information about this error, try `rustc --explain E0380`. diff --git a/src/test/ui/bad/bad-method-typaram-kind.stderr b/src/test/ui/bad/bad-method-typaram-kind.stderr index 740667f146680..c72b965236006 100644 --- a/src/test/ui/bad/bad-method-typaram-kind.stderr +++ b/src/test/ui/bad/bad-method-typaram-kind.stderr @@ -1,12 +1,11 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/bad-method-typaram-kind.rs:2:7 | -LL | fn foo() { - | -- help: consider further restricting this bound: `T: std::marker::Send +` LL | 1.bar::(); | ^^^ `T` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `T` + = help: consider adding a `where T: std::marker::Send` bound error: aborting due to previous error diff --git a/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs b/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs index 4e0a238c5d48d..ea4a9e5afa501 100644 --- a/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs +++ b/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs @@ -2,7 +2,7 @@ // Check that partially moved from function parameters are dropped after the // named bindings that move from them. -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default use std::{panic, cell::RefCell}; diff --git a/src/test/ui/binding/match-arm-statics.rs b/src/test/ui/binding/match-arm-statics.rs index e6d17def1477e..5f7e357eeb2a9 100644 --- a/src/test/ui/binding/match-arm-statics.rs +++ b/src/test/ui/binding/match-arm-statics.rs @@ -1,7 +1,6 @@ // run-pass #![allow(dead_code)] // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet #[derive(PartialEq, Eq)] struct NewBool(bool); diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.polonius.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.polonius.stderr new file mode 100644 index 0000000000000..89af8764557ff --- /dev/null +++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.polonius.stderr @@ -0,0 +1,16 @@ +error[E0597]: `books` does not live long enough + --> $DIR/borrowck-escaping-closure-error-2.rs:11:17 + | +LL | Box::new(|| books.push(4)) + | ------------^^^^^--------- + | | | | + | | | borrowed value does not live long enough + | | value captured here + | borrow later used here +LL | +LL | } + | - `books` 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/borrowck/issue-64453.rs b/src/test/ui/borrowck/issue-64453.rs deleted file mode 100644 index d8ab6b6e25f6f..0000000000000 --- a/src/test/ui/borrowck/issue-64453.rs +++ /dev/null @@ -1,24 +0,0 @@ -struct Project; -struct Value; - -static settings_dir: String = format!(""); -//~^ ERROR [E0019] -//~| ERROR [E0015] -//~| ERROR [E0015] - -fn from_string(_: String) -> Value { - Value -} -fn set_editor(_: Value) {} - -fn main() { - let settings_data = from_string(settings_dir); - //~^ ERROR cannot move out of static item `settings_dir` [E0507] - let args: i32 = 0; - - match args { - ref x if x == &0 => set_editor(settings_data), - ref x if x == &1 => set_editor(settings_data), - _ => unimplemented!(), - } -} diff --git a/src/test/ui/borrowck/issue-64453.stderr b/src/test/ui/borrowck/issue-64453.stderr deleted file mode 100644 index 6987417fe192e..0000000000000 --- a/src/test/ui/borrowck/issue-64453.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error[E0507]: cannot move out of static item `settings_dir` - --> $DIR/issue-64453.rs:15:37 - | -LL | let settings_data = from_string(settings_dir); - | ^^^^^^^^^^^^ move occurs because `settings_dir` has type `std::string::String`, which does not implement the `Copy` trait - -error[E0019]: static contains unimplemented expression type - --> $DIR/issue-64453.rs:4:31 - | -LL | static settings_dir: String = format!(""); - | ^^^^^^^^^^^ - | - = 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[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants - --> $DIR/issue-64453.rs:4:31 - | -LL | static settings_dir: String = format!(""); - | ^^^^^^^^^^^ - | - = 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[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants - --> $DIR/issue-64453.rs:4:31 - | -LL | static settings_dir: String = format!(""); - | ^^^^^^^^^^^ - | - = 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 4 previous errors - -Some errors have detailed explanations: E0015, E0019, E0507. -For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.polonius.stderr b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.polonius.stderr new file mode 100644 index 0000000000000..a5b2e8762746c --- /dev/null +++ b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.polonius.stderr @@ -0,0 +1,59 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:5:21 + | +LL | let ref mut x = 1234543; + | ^^^^^^^ creates a temporary which is freed while still in use +LL | x + | - borrow later used here +LL | } + | - temporary value is freed at the end of this statement + | + = note: consider using a `let` binding to create a longer lived value + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:10:25 + | +LL | let (ref mut x, ) = (1234543, ); + | ^^^^^^^^^^^ creates a temporary which is freed while still in use +LL | x + | - borrow later used here +LL | } + | - temporary value is freed at the end of this statement + | + = note: consider using a `let` binding to create a longer lived value + +error[E0515]: cannot return value referencing temporary value + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:15:5 + | +LL | match 1234543 { + | ^ ------- temporary value created here + | _____| + | | +LL | | ref mut x => x +LL | | } + | |_____^ returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:21:5 + | +LL | match (123443,) { + | ^ --------- temporary value created here + | _____| + | | +LL | | (ref mut x,) => x, +LL | | } + | |_____^ returns a value referencing data owned by the current function + +error[E0515]: cannot return reference to temporary value + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:27:5 + | +LL | &mut 1234543 + | ^^^^^------- + | | | + | | temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0515, E0716. +For more information about an error, try `rustc --explain E0515`. diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr index 52d43eae658ae..4c7c0d1a0dfa5 100644 --- a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr +++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -24,12 +24,12 @@ LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d | = note: expected type `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)` found type `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)` -note: the lifetime `'c` as defined on the method body at 27:24... +note: the lifetime 'c as defined on the method body at 27:24... --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^ -note: ...does not necessarily outlive the lifetime `'c` as defined on the method body at 27:24 +note: ...does not necessarily outlive the lifetime 'c as defined on the method body at 27:24 --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { 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 0000000000000..c818379762c9d --- /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-surprise-no-conflict.polonius.stderr b/src/test/ui/borrowck/two-phase-surprise-no-conflict.polonius.stderr new file mode 100644 index 0000000000000..7b246426a2333 --- /dev/null +++ b/src/test/ui/borrowck/two-phase-surprise-no-conflict.polonius.stderr @@ -0,0 +1,148 @@ +error[E0503]: cannot use `self.cx` because it was mutably borrowed + --> $DIR/two-phase-surprise-no-conflict.rs:21:23 + | +LL | let _mut_borrow = &mut *self; + | ---------- borrow of `*self` occurs here +LL | let _access = self.cx; + | ^^^^^^^ use of borrowed `*self` +LL | +LL | _mut_borrow; + | ----------- borrow later used here + +error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-surprise-no-conflict.rs:57:17 + | +LL | self.hash_expr(&self.cx_mut.body(eid).value); + | ^^^^^---------^^-----------^^^^^^^^^^^^^^^^^ + | | | | + | | | immutable borrow occurs here + | | immutable borrow later used by call + | mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:119:51 + | +LL | reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut))); + | --- --------------- ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here + | | | + | | first borrow later used by call + | first mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:122:54 + | +LL | reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + | --- -------------- ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here + | | | + | | first borrow later used by call + | first mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:125:53 + | +LL | reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + | --- ------------- ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here + | | | + | | first borrow later used by call + | first mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:128:44 + | +LL | reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut)); + | --- ------------ ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here + | | | + | | first borrow later used by call + | first mutable borrow occurs here + +error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-surprise-no-conflict.rs:138:5 + | +LL | reg.register_bound(Box::new(CapturePass::new(®.sess_mut))); + | ^^^^--------------^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^ + | | | | + | | | immutable borrow occurs here + | | immutable borrow later used by call + | mutable borrow occurs here + +error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-surprise-no-conflict.rs:141:5 + | +LL | reg.register_univ(Box::new(CapturePass::new(®.sess_mut))); + | ^^^^-------------^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^ + | | | | + | | | immutable borrow occurs here + | | immutable borrow later used by call + | mutable borrow occurs here + +error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-surprise-no-conflict.rs:144:5 + | +LL | reg.register_ref(&CapturePass::new(®.sess_mut)); + | ^^^^------------^^^^^^^^^^^^^^^^^^^-------------^^ + | | | | + | | | immutable borrow occurs here + | | immutable borrow later used by call + | mutable borrow occurs here + +error[E0499]: cannot borrow `*reg` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:154:5 + | +LL | reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | ^^^^--------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^ + | | | | + | | | first mutable borrow occurs here + | | first borrow later used by call + | second mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:154:54 + | +LL | reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | --- -------------- ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here + | | | + | | first borrow later used by call + | first mutable borrow occurs here + +error[E0499]: cannot borrow `*reg` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:158:5 + | +LL | reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | ^^^^-------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^ + | | | | + | | | first mutable borrow occurs here + | | first borrow later used by call + | second mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:158:53 + | +LL | reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | --- ------------- ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here + | | | + | | first borrow later used by call + | first mutable borrow occurs here + +error[E0499]: cannot borrow `*reg` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:162:5 + | +LL | reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut)); + | ^^^^------------^^^^^^^^^^^^^^^^^^^^^^^-----------------^^ + | | | | + | | | first mutable borrow occurs here + | | first borrow later used by call + | second mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:162:44 + | +LL | reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut)); + | --- ------------ ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here + | | | + | | first borrow later used by call + | first mutable borrow occurs here + +error: aborting due to 15 previous errors + +Some errors have detailed explanations: E0499, E0502, E0503. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/break-outside-loop.rs b/src/test/ui/break-outside-loop.rs index a6f9d0423d082..c424c25c646bd 100644 --- a/src/test/ui/break-outside-loop.rs +++ b/src/test/ui/break-outside-loop.rs @@ -22,12 +22,4 @@ fn main() { let rs: Foo = Foo{t: pth}; 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 8e300fd848dab..8b686356055a3 100644 --- a/src/test/ui/break-outside-loop.stderr +++ b/src/test/ui/break-outside-loop.stderr @@ -33,15 +33,7 @@ error[E0268]: `break` outside of a loop LL | let unconstrained = break; | ^^^^^ 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 6 previous errors +error: aborting due to 5 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/builtin-clone-unwind.rs b/src/test/ui/builtin-clone-unwind.rs index 1fd91440a7884..339bcfa1060a4 100644 --- a/src/test/ui/builtin-clone-unwind.rs +++ b/src/test/ui/builtin-clone-unwind.rs @@ -2,7 +2,7 @@ #![allow(unused_variables)] #![allow(unused_imports)] -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // Test that builtin implementations of `Clone` cleanup everything // in case of unwinding. diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr index 5be6ab05d6607..9771436d167df 100644 --- a/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr +++ b/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr @@ -2,22 +2,20 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/builtin-superkinds-double-superkind.rs:6:24 | LL | impl Foo for (T,) { } - | -- ^^^ `T` cannot be sent between threads safely - | | - | help: consider further restricting this bound: `T: std::marker::Send +` + | ^^^ `T` cannot be sent between threads safely | = help: within `(T,)`, the trait `std::marker::Send` is not implemented for `T` + = help: consider adding a `where T: std::marker::Send` bound = note: required because it appears within the type `(T,)` error[E0277]: `T` cannot be shared between threads safely --> $DIR/builtin-superkinds-double-superkind.rs:9:16 | LL | impl Foo for (T,T) { } - | -- ^^^ `T` cannot be shared between threads safely - | | - | help: consider further restricting this bound: `T: std::marker::Sync +` + | ^^^ `T` cannot be shared between threads safely | = help: within `(T, T)`, the trait `std::marker::Sync` is not implemented for `T` + = help: consider adding a `where T: std::marker::Sync` bound = note: required because it appears within the type `(T, T)` error: aborting due to 2 previous errors diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr index 8cce9bfdf52a8..61c18a24fb0c9 100644 --- a/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr +++ b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr @@ -2,11 +2,10 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/builtin-superkinds-in-metadata.rs:13:23 | LL | impl RequiresRequiresShareAndSend for X { } - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be sent between threads safely - | | - | help: consider further restricting this bound: `T: std::marker::Send +` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be sent between threads safely | = help: within `X`, the trait `std::marker::Send` is not implemented for `T` + = help: consider adding a `where T: std::marker::Send` bound = note: required because it appears within the type `X` error: aborting due to previous error diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr index 4381a5b868262..dc5479e5e2da6 100644 --- a/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr +++ b/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr @@ -2,11 +2,10 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/builtin-superkinds-typaram-not-send.rs:5:24 | LL | impl Foo for T { } - | -- ^^^ `T` cannot be sent between threads safely - | | - | help: consider further restricting this bound: `T: std::marker::Send +` + | ^^^ `T` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `T` + = help: consider adding a `where T: std::marker::Send` bound error: aborting due to previous error diff --git a/src/test/ui/c-variadic/variadic-ffi-1.stderr b/src/test/ui/c-variadic/variadic-ffi-1.stderr index 73f72a177bcaa..695eba2a7ee40 100644 --- a/src/test/ui/c-variadic/variadic-ffi-1.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-1.stderr @@ -29,7 +29,7 @@ LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo; | ^^^ expected non-variadic fn, found variadic function | = note: expected type `unsafe extern "C" fn(isize, u8)` - found type `unsafe extern "C" fn(isize, u8, ...) {foo}` + found type `for<'r> unsafe extern "C" fn(isize, u8, std::ffi::VaListImpl<'r>, ...) {foo}` error[E0308]: mismatched types --> $DIR/variadic-ffi-1.rs:20:54 @@ -37,7 +37,7 @@ error[E0308]: mismatched types LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar; | ^^^ expected variadic fn, found non-variadic function | - = note: expected type `extern "C" fn(isize, u8, ...)` + = note: expected type `for<'r> extern "C" fn(isize, u8, std::ffi::VaListImpl<'r>, ...)` found type `extern "C" fn(isize, u8) {bar}` error[E0617]: can't pass `f32` to variadic function 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 8b70b15fa6e50..ab8398ec5e935 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr @@ -1,30 +1,18 @@ -error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:8:5 - | -LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { - | -- -- has type `core::ffi::VaListImpl<'1>` - | | - | lifetime `'f` defined here -LL | ap - | ^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'f` - -error: lifetime may not live long enough +error[E0621]: explicit lifetime required in the type of `ap` --> $DIR/variadic-ffi-4.rs:8:5 | LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { - | -- -- has type `core::ffi::VaListImpl<'1>` - | | - | lifetime `'f` defined here + | --- help: add explicit lifetime `'f` to the type of `ap`: `core::ffi::VaListImpl<'f>` LL | ap - | ^^ returning this value requires that `'1` must outlive `'f` + | ^^ lifetime `'f` required -error: lifetime may not live long enough +error[E0621]: explicit lifetime required in the type of `ap` --> $DIR/variadic-ffi-4.rs:12:5 | LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> { - | -- has type `core::ffi::VaListImpl<'1>` + | --- help: add explicit lifetime `'static` to the type of `ap`: `core::ffi::VaListImpl<'static>` LL | ap - | ^^ returning this value requires that `'1` must outlive `'static` + | ^^ lifetime `'static` required error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:16:33 @@ -56,7 +44,7 @@ LL | *ap0 = ap1; | ^^^^ assignment requires that `'2` must outlive `'1` error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:24:5 + --> $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<'2>` @@ -66,7 +54,7 @@ LL | ap0 = &mut ap1; | ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2` error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:24:5 + --> $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<'2>` @@ -76,7 +64,7 @@ LL | ap0 = &mut ap1; | ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1` error[E0384]: cannot assign to immutable argument `ap0` - --> $DIR/variadic-ffi-4.rs:24:5 + --> $DIR/variadic-ffi-4.rs:25:5 | LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { | --- help: make this binding mutable: `mut ap0` @@ -84,7 +72,7 @@ LL | ap0 = &mut ap1; | ^^^^^^^^^^^^^^ cannot assign to immutable argument error[E0597]: `ap1` does not live long enough - --> $DIR/variadic-ffi-4.rs:24:11 + --> $DIR/variadic-ffi-4.rs:25:11 | LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { | - let's call the lifetime of this reference `'1` @@ -98,7 +86,7 @@ LL | } | - `ap1` dropped here while still borrowed error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:31:12 + --> $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<'2>` @@ -108,7 +96,7 @@ LL | *ap0 = ap1.clone(); | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2` error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:31:12 + --> $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<'2>` @@ -117,7 +105,7 @@ LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut LL | *ap0 = ap1.clone(); | ^^^^^^^^^^^ argument requires that `'2` must outlive `'1` -error: aborting due to 12 previous errors +error: aborting due to 11 previous errors -Some errors have detailed explanations: E0384, E0597. +Some errors have detailed explanations: E0384, E0597, E0621. For more information about an error, try `rustc --explain E0384`. diff --git a/src/test/ui/c-variadic/variadic-ffi-4.rs b/src/test/ui/c-variadic/variadic-ffi-4.rs index a4d658cef1630..4a50d352a5b20 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.rs +++ b/src/test/ui/c-variadic/variadic-ffi-4.rs @@ -5,11 +5,11 @@ use core::ffi::{VaList, VaListImpl}; pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { - ap //~ ERROR: mismatched types + ap //~ ERROR: explicit lifetime required } pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> { - ap //~ ERROR: mismatched types + ap //~ ERROR: explicit lifetime required } pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) { @@ -18,15 +18,18 @@ pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) { pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { *ap0 = ap1; //~ ERROR: mismatched types + //~^ ERROR: mismatched types } pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { ap0 = &mut ap1; //~^ ERROR: a value of type `core::ffi::VaListImpl<'_>` is borrowed for too long - //~| ERROR: mismatched types - //~| ERROR: cannot infer an appropriate lifetime + //~^^ ERROR: mismatched types + //~^^^ ERROR: mismatched types + //~^^^^ ERROR: cannot infer an appropriate lifetime } pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { *ap0 = ap1.clone(); //~ ERROR: mismatched types + //~^ ERROR: mismatched types } diff --git a/src/test/ui/c-variadic/variadic-ffi-4.stderr b/src/test/ui/c-variadic/variadic-ffi-4.stderr index 05535659161b8..7aa510e611304 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-4.stderr @@ -1,42 +1,18 @@ -error[E0308]: mismatched types +error[E0621]: explicit lifetime required in the type of `ap` --> $DIR/variadic-ffi-4.rs:8:5 | -LL | ap - | ^^ lifetime mismatch - | - = note: expected type `core::ffi::VaListImpl<'f>` - found type `core::ffi::VaListImpl<'_>` -note: the scope of call-site for function at 7:78... - --> $DIR/variadic-ffi-4.rs:7:78 - | -LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { - | ______________________________________________________________________________^ -LL | | ap -LL | | } - | |_^ -note: ...does not necessarily outlive the lifetime `'f` as defined on the function body at 7:37 - --> $DIR/variadic-ffi-4.rs:7:37 - | LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { - | ^^ + | --- help: add explicit lifetime `'f` to the type of `ap`: `core::ffi::VaListImpl<'f>` +LL | ap + | ^^ lifetime `'f` required -error[E0308]: mismatched types +error[E0621]: explicit lifetime required in the type of `ap` --> $DIR/variadic-ffi-4.rs:12:5 | +LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> { + | --- help: add explicit lifetime `'static` to the type of `ap`: `core::ffi::VaListImpl<'static>` LL | ap - | ^^ lifetime mismatch - | - = note: expected type `core::ffi::VaListImpl<'static>` - found type `core::ffi::VaListImpl<'_>` -note: the scope of call-site for function at 11:79... - --> $DIR/variadic-ffi-4.rs:11:79 - | -LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> { - | _______________________________________________________________________________^ -LL | | ap -LL | | } - | |_^ - = note: ...does not necessarily outlive the static lifetime + | ^^ lifetime `'static` required error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> $DIR/variadic-ffi-4.rs:16:33 @@ -71,12 +47,12 @@ LL | *ap0 = ap1; | = note: expected type `core::ffi::VaListImpl<'_>` found type `core::ffi::VaListImpl<'_>` -note: the scope of call-site for function at 19:87... - --> $DIR/variadic-ffi-4.rs:19:87 +note: the anonymous lifetime #3 defined on the function body at 19:1... + --> $DIR/variadic-ffi-4.rs:19:1 | -LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { - | _______________________________________________________________________________________^ +LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { LL | | *ap0 = ap1; +LL | | LL | | } | |_^ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 19:1 @@ -84,130 +60,216 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the f | LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { LL | | *ap0 = ap1; +LL | | +LL | | } + | |_^ + +error[E0308]: mismatched types + --> $DIR/variadic-ffi-4.rs:20:12 + | +LL | *ap0 = ap1; + | ^^^ lifetime mismatch + | + = note: expected type `core::ffi::VaListImpl<'_>` + found type `core::ffi::VaListImpl<'_>` +note: the anonymous lifetime #2 defined on the function body at 19:1... + --> $DIR/variadic-ffi-4.rs:19:1 + | +LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { +LL | | *ap0 = ap1; +LL | | +LL | | } + | |_^ +note: ...does not necessarily outlive the anonymous lifetime #3 defined on the function body at 19:1 + --> $DIR/variadic-ffi-4.rs:19:1 + | +LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { +LL | | *ap0 = ap1; +LL | | LL | | } | |_^ error[E0490]: a value of type `core::ffi::VaListImpl<'_>` is borrowed for too long - --> $DIR/variadic-ffi-4.rs:24:11 + --> $DIR/variadic-ffi-4.rs:25:11 | LL | ap0 = &mut ap1; | ^^^^^^^^ | -note: the type is valid for the anonymous lifetime #1 defined on the function body at 23:1 - --> $DIR/variadic-ffi-4.rs:23:1 +note: the type is valid for the anonymous lifetime #1 defined on the function body at 24:1 + --> $DIR/variadic-ffi-4.rs:24:1 + | +LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { +LL | | ap0 = &mut ap1; +LL | | +LL | | +LL | | +LL | | +LL | | } + | |_^ +note: but the borrow lasts for the anonymous lifetime #3 defined on the function body at 24:1 + --> $DIR/variadic-ffi-4.rs:24:1 + | +LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { +LL | | ap0 = &mut ap1; +LL | | +LL | | +LL | | +LL | | +LL | | } + | |_^ + +error[E0308]: mismatched types + --> $DIR/variadic-ffi-4.rs:25:11 + | +LL | ap0 = &mut ap1; + | ^^^^^^^^ lifetime mismatch + | + = note: expected type `&mut core::ffi::VaListImpl<'_>` + found type `&mut core::ffi::VaListImpl<'_>` +note: the anonymous lifetime #3 defined on the function body at 24:1... + --> $DIR/variadic-ffi-4.rs:24:1 | LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { LL | | ap0 = &mut ap1; LL | | LL | | LL | | +LL | | LL | | } | |_^ -note: but the borrow lasts for the scope of call-site for function at 23:83 - --> $DIR/variadic-ffi-4.rs:23:83 +note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 24:1 + --> $DIR/variadic-ffi-4.rs:24:1 | -LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { - | ___________________________________________________________________________________^ +LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { LL | | ap0 = &mut ap1; LL | | LL | | LL | | +LL | | LL | | } | |_^ error[E0308]: mismatched types - --> $DIR/variadic-ffi-4.rs:24:11 + --> $DIR/variadic-ffi-4.rs:25:11 | LL | ap0 = &mut ap1; | ^^^^^^^^ lifetime mismatch | = note: expected type `&mut core::ffi::VaListImpl<'_>` found type `&mut core::ffi::VaListImpl<'_>` -note: the scope of call-site for function at 23:83... - --> $DIR/variadic-ffi-4.rs:23:83 +note: the anonymous lifetime #2 defined on the function body at 24:1... + --> $DIR/variadic-ffi-4.rs:24:1 | -LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { - | ___________________________________________________________________________________^ +LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { LL | | ap0 = &mut ap1; LL | | LL | | LL | | +LL | | LL | | } | |_^ -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 23:1 - --> $DIR/variadic-ffi-4.rs:23:1 +note: ...does not necessarily outlive the anonymous lifetime #3 defined on the function body at 24:1 + --> $DIR/variadic-ffi-4.rs:24:1 | LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { LL | | ap0 = &mut ap1; LL | | LL | | LL | | +LL | | LL | | } | |_^ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements - --> $DIR/variadic-ffi-4.rs:24:11 + --> $DIR/variadic-ffi-4.rs:25:11 | LL | ap0 = &mut ap1; | ^^^^^^^^ | -note: first, the lifetime cannot outlive the scope of call-site for function at 23:83... - --> $DIR/variadic-ffi-4.rs:23:83 +note: first, the lifetime cannot outlive the anonymous lifetime #3 defined on the function body at 24:1... + --> $DIR/variadic-ffi-4.rs:24:1 | -LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { - | ___________________________________________________________________________________^ +LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { LL | | ap0 = &mut ap1; LL | | LL | | LL | | +LL | | LL | | } | |_^ note: ...so that the type `core::ffi::VaListImpl<'_>` is not borrowed for too long - --> $DIR/variadic-ffi-4.rs:24:11 + --> $DIR/variadic-ffi-4.rs:25:11 | LL | ap0 = &mut ap1; | ^^^^^^^^ -note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 23:1... - --> $DIR/variadic-ffi-4.rs:23:1 +note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 24:1... + --> $DIR/variadic-ffi-4.rs:24:1 | LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { LL | | ap0 = &mut ap1; LL | | LL | | LL | | +LL | | LL | | } | |_^ note: ...so that reference does not outlive borrowed content - --> $DIR/variadic-ffi-4.rs:24:11 + --> $DIR/variadic-ffi-4.rs:25:11 | LL | ap0 = &mut ap1; | ^^^^^^^^ error[E0308]: mismatched types - --> $DIR/variadic-ffi-4.rs:31:12 + --> $DIR/variadic-ffi-4.rs:33:12 | LL | *ap0 = ap1.clone(); | ^^^^^^^^^^^ lifetime mismatch | = note: expected type `core::ffi::VaListImpl<'_>` found type `core::ffi::VaListImpl<'_>` -note: the scope of call-site for function at 30:87... - --> $DIR/variadic-ffi-4.rs:30:87 +note: the anonymous lifetime #3 defined on the function body at 32:1... + --> $DIR/variadic-ffi-4.rs:32:1 | -LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { - | _______________________________________________________________________________________^ +LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { LL | | *ap0 = ap1.clone(); +LL | | LL | | } | |_^ -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 30:1 - --> $DIR/variadic-ffi-4.rs:30:1 +note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 32:1 + --> $DIR/variadic-ffi-4.rs:32:1 | LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { LL | | *ap0 = ap1.clone(); +LL | | +LL | | } + | |_^ + +error[E0308]: mismatched types + --> $DIR/variadic-ffi-4.rs:33:12 + | +LL | *ap0 = ap1.clone(); + | ^^^^^^^^^^^ lifetime mismatch + | + = note: expected type `core::ffi::VaListImpl<'_>` + found type `core::ffi::VaListImpl<'_>` +note: the anonymous lifetime #2 defined on the function body at 32:1... + --> $DIR/variadic-ffi-4.rs:32:1 + | +LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { +LL | | *ap0 = ap1.clone(); +LL | | +LL | | } + | |_^ +note: ...does not necessarily outlive the anonymous lifetime #3 defined on the function body at 32:1 + --> $DIR/variadic-ffi-4.rs:32:1 + | +LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { +LL | | *ap0 = ap1.clone(); +LL | | LL | | } | |_^ -error: aborting due to 8 previous errors +error: aborting due to 11 previous errors -Some errors have detailed explanations: E0308, E0495. +Some errors have detailed explanations: E0308, E0621. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/never_type/call-fn-never-arg-wrong-type.rs b/src/test/ui/call-fn-never-arg-wrong-type.rs similarity index 100% rename from src/test/ui/never_type/call-fn-never-arg-wrong-type.rs rename to src/test/ui/call-fn-never-arg-wrong-type.rs diff --git a/src/test/ui/never_type/call-fn-never-arg-wrong-type.stderr b/src/test/ui/call-fn-never-arg-wrong-type.stderr similarity index 100% rename from src/test/ui/never_type/call-fn-never-arg-wrong-type.stderr rename to src/test/ui/call-fn-never-arg-wrong-type.stderr diff --git a/src/test/ui/catch-unwind-bang.rs b/src/test/ui/catch-unwind-bang.rs index c2c21bca7ef71..f181991713b2c 100644 --- a/src/test/ui/catch-unwind-bang.rs +++ b/src/test/ui/catch-unwind-bang.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default fn worker() -> ! { panic!() diff --git a/src/test/ui/cfg/cfg_stmt_expr.rs b/src/test/ui/cfg/cfg_stmt_expr.rs index 6381bb2d58877..e466ad69f721c 100644 --- a/src/test/ui/cfg/cfg_stmt_expr.rs +++ b/src/test/ui/cfg/cfg_stmt_expr.rs @@ -57,7 +57,7 @@ fn main() { // check that macro expanded code works macro_rules! if_cfg { - ($cfg:meta? $ib:block else $eb:block) => { + ($cfg:meta $ib:block else $eb:block) => { { let r; #[cfg($cfg)] @@ -69,7 +69,7 @@ fn main() { } } - let n = if_cfg!(unset? { + let n = if_cfg!(unset { 413 } else { 612 diff --git a/src/test/ui/check-static-values-constraints.stderr b/src/test/ui/check-static-values-constraints.stderr index 7d7ecbd1a26a5..a13c217483d5d 100644 --- a/src/test/ui/check-static-values-constraints.stderr +++ b/src/test/ui/check-static-values-constraints.stderr @@ -108,5 +108,5 @@ LL | let y = { static x: Box = box 3; x }; error: aborting due to 17 previous errors -Some errors have detailed explanations: E0010, E0015, E0019, E0493, E0507. +Some errors have detailed explanations: E0010, E0015, E0019, E0507. For more information about an error, try `rustc --explain E0010`. diff --git a/src/test/ui/check_match/issue-43253.rs b/src/test/ui/check_match/issue-43253.rs index 5c6834459f0d4..a4d6e9b777f02 100644 --- a/src/test/ui/check_match/issue-43253.rs +++ b/src/test/ui/check_match/issue-43253.rs @@ -1,7 +1,7 @@ -// check-pass +// build-pass (FIXME(62277): could be check-pass?) + #![feature(exclusive_range_pattern)] #![warn(unreachable_patterns)] -#![warn(overlapping_patterns)] fn main() { // These cases should generate no warning. @@ -13,7 +13,7 @@ fn main() { match 10 { 1..10 => {}, - 9..=10 => {}, //~ WARNING multiple patterns covering the same range + 9..=10 => {}, _ => {}, } @@ -23,25 +23,22 @@ fn main() { _ => {}, } - // These cases should generate "unreachable pattern" warnings. + // These cases should generate an "unreachable pattern" warning. match 10 { 1..10 => {}, - 9 => {}, //~ WARNING unreachable pattern + 9 => {}, _ => {}, } match 10 { 1..10 => {}, - 8..=9 => {}, //~ WARNING multiple patterns covering the same range + 8..=9 => {}, _ => {}, } match 10 { - 5..7 => {}, - 6 => {}, //~ WARNING unreachable pattern - 1..10 => {}, //~ WARNING multiple patterns covering the same range - 9..=9 => {}, //~ WARNING unreachable pattern - 6 => {}, //~ WARNING unreachable pattern + 1..10 => {}, + 9..=9 => {}, _ => {}, } } diff --git a/src/test/ui/check_match/issue-43253.stderr b/src/test/ui/check_match/issue-43253.stderr index cb4a0486eef9a..d961f623e1fa7 100644 --- a/src/test/ui/check_match/issue-43253.stderr +++ b/src/test/ui/check_match/issue-43253.stderr @@ -1,17 +1,3 @@ -warning: multiple patterns covering the same range - --> $DIR/issue-43253.rs:16:9 - | -LL | 1..10 => {}, - | ----- this range overlaps on `9i32` -LL | 9..=10 => {}, - | ^^^^^^ overlapping patterns - | -note: lint level defined here - --> $DIR/issue-43253.rs:4:9 - | -LL | #![warn(overlapping_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - warning: unreachable pattern --> $DIR/issue-43253.rs:29:9 | @@ -19,7 +5,7 @@ LL | 9 => {}, | ^ | note: lint level defined here - --> $DIR/issue-43253.rs:3:9 + --> $DIR/issue-43253.rs:4:9 | LL | #![warn(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ @@ -33,18 +19,6 @@ LL | 8..=9 => {}, warning: unreachable pattern --> $DIR/issue-43253.rs:41:9 | -LL | 6 => {}, - | ^ - -warning: unreachable pattern - --> $DIR/issue-43253.rs:43:9 - | LL | 9..=9 => {}, | ^^^^^ -warning: unreachable pattern - --> $DIR/issue-43253.rs:44:9 - | -LL | 6 => {}, - | ^ - 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 8af7f882cc299..ac4666fe36de6 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 @@ -11,7 +11,7 @@ note: the anonymous lifetime #2 defined on the body at 14:48... | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 11:36 +note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 11:36 --> $DIR/expect-fn-supply-fn.rs:11:36 | LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { @@ -25,7 +25,7 @@ LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | = note: expected type `fn(&u32)` found type `fn(&'x u32)` -note: the lifetime `'x` as defined on the function body at 11:36... +note: the lifetime 'x as defined on the function body at 11:36... --> $DIR/expect-fn-supply-fn.rs:11:36 | LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { 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 3c8f637e13369..51077b1b2922e 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 @@ -4,16 +4,14 @@ error[E0277]: `F` cannot be sent between threads safely LL | struct X where F: FnOnce() + 'static + Send { | ---------------------------------------------- required by `X` ... -LL | fn foo(blk: F) -> X where F: FnOnce() + 'static { - | ^ - help: consider further restricting type parameter `F`: `, F: std::marker::Send` - | _| - | | +LL | / fn foo(blk: F) -> X where F: FnOnce() + 'static { LL | | LL | | return X { field: blk }; LL | | } | |_^ `F` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `F` + = help: consider adding a `where F: std::marker::Send` bound 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 05d5bb1e8d5a8..4b703eded69c3 100644 --- a/src/test/ui/closures/closure-bounds-subtype.stderr +++ b/src/test/ui/closures/closure-bounds-subtype.stderr @@ -4,13 +4,11 @@ error[E0277]: `F` cannot be shared between threads safely LL | fn take_const_owned(_: F) where F: FnOnce() + Sync + Send { | ---------------- ---- required by this bound in `take_const_owned` ... -LL | fn give_owned(f: F) where F: FnOnce() + Send { - | - help: consider further restricting type parameter `F`: `, F: std::marker::Sync` -LL | take_any(f); LL | take_const_owned(f); | ^ `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 error: aborting due to previous error diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr index 9f74738315a0a..e3b623d55248e 100644 --- a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr +++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr @@ -38,7 +38,7 @@ LL | | LL | | LL | | }); | |_____^ -note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 32:30 +note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 32:30 --> $DIR/expect-region-supply-region.rs:32:30 | LL | fn expect_bound_supply_named<'x>() { @@ -52,7 +52,7 @@ LL | closure_expecting_bound(|x: &'x u32| { | = note: expected type `&u32` found type `&'x u32` -note: the lifetime `'x` as defined on the function body at 32:30... +note: the lifetime 'x as defined on the function body at 32:30... --> $DIR/expect-region-supply-region.rs:32:30 | LL | fn expect_bound_supply_named<'x>() { diff --git a/src/test/ui/closures/issue-41366.rs b/src/test/ui/closures/issue-41366.rs deleted file mode 100644 index 5cae0e76d1acb..0000000000000 --- a/src/test/ui/closures/issue-41366.rs +++ /dev/null @@ -1,13 +0,0 @@ -trait T<'x> { - type V; -} - -impl<'g> T<'g> for u32 { - type V = u16; -} - -fn main() { - (&|_|()) as &dyn for<'x> Fn(>::V); - //~^ ERROR: type mismatch in closure arguments - //~| ERROR: type mismatch resolving -} diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr deleted file mode 100644 index 91d26efbc4f35..0000000000000 --- a/src/test/ui/closures/issue-41366.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/issue-41366.rs:10:5 - | -LL | (&|_|()) as &dyn for<'x> Fn(>::V); - | ^^-----^ - | | | - | | found signature of `fn(_) -> _` - | expected signature of `for<'x> fn(>::V) -> _` - | - = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(>::V)` - -error[E0271]: type mismatch resolving `for<'x> <[closure@$DIR/issue-41366.rs:10:7: 10:12] as std::ops::FnOnce<(>::V,)>>::Output == ()` - --> $DIR/issue-41366.rs:10:5 - | -LL | (&|_|()) as &dyn for<'x> Fn(>::V); - | ^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime - | - = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(>::V)` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/closures/issue-52437.rs b/src/test/ui/closures/issue-52437.rs deleted file mode 100644 index 6ac5380a5aa23..0000000000000 --- a/src/test/ui/closures/issue-52437.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - [(); &(&'static: loop { |x| {}; }) as *const _ as usize] - //~^ ERROR: invalid label name `'static` - //~| ERROR: type annotations needed -} diff --git a/src/test/ui/closures/issue-52437.stderr b/src/test/ui/closures/issue-52437.stderr deleted file mode 100644 index e76f942e9ba57..0000000000000 --- a/src/test/ui/closures/issue-52437.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: invalid label name `'static` - --> $DIR/issue-52437.rs:2:13 - | -LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] - | ^^^^^^^ - -error[E0282]: type annotations needed - --> $DIR/issue-52437.rs:2:30 - | -LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] - | ^ consider giving this closure parameter a type - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.rs b/src/test/ui/coercion/coerce-issue-49593-box-never.rs index 5038eb3ebf458..f005245e6dcb9 100644 --- a/src/test/ui/coercion/coerce-issue-49593-box-never.rs +++ b/src/test/ui/coercion/coerce-issue-49593-box-never.rs @@ -1,4 +1,4 @@ -// check-pass +// build-pass (FIXME(62277): could be check-pass?) #![feature(never_type)] #![allow(unreachable_code)] diff --git a/src/test/ui/coherence/auxiliary/coherence_lib.rs b/src/test/ui/coherence/auxiliary/coherence_lib.rs index c22819831ab24..9a5ec82430639 100644 --- a/src/test/ui/coherence/auxiliary/coherence_lib.rs +++ b/src/test/ui/coherence/auxiliary/coherence_lib.rs @@ -5,11 +5,11 @@ pub trait Remote { } pub trait Remote1 { - fn foo(&self, _t: T) { } + fn foo(&self, t: T) { } } pub trait Remote2 { - fn foo(&self, _t: T, _u: U) { } + fn foo(&self, t: T, u: U) { } } pub struct Pair(T,U); diff --git a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs deleted file mode 100644 index 9859a226efd00..0000000000000 --- a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Check that unsafe trait object do not implement themselves -// automatically - -#![feature(object_safe_for_dispatch)] - -trait Trait: Sized { - fn call(&self); -} - -fn takes_t(s: S) { - s.call(); -} - -fn takes_t_obj(t: &dyn Trait) { - takes_t(t); //~ ERROR E0277 -} - -fn main() {} diff --git a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr deleted file mode 100644 index b5a86acfb978f..0000000000000 --- a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0277]: the trait bound `&dyn Trait: Trait` is not satisfied - --> $DIR/coherence-unsafe-trait-object-impl.rs:15:13 - | -LL | fn takes_t(s: S) { - | ------- ----- required by this bound in `takes_t` -... -LL | takes_t(t); - | ^ the trait `Trait` is not implemented for `&dyn Trait` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/coherence/coherence_inherent.old.stderr b/src/test/ui/coherence/coherence_inherent.old.stderr index e71547cb89f9c..750d243480638 100644 --- a/src/test/ui/coherence/coherence_inherent.old.stderr +++ b/src/test/ui/coherence/coherence_inherent.old.stderr @@ -5,7 +5,7 @@ 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: + = note: the following trait is implemented but not in scope, perhaps add a `use` for it: `use Lib::TheTrait;` error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_inherent.re.stderr b/src/test/ui/coherence/coherence_inherent.re.stderr index e71547cb89f9c..750d243480638 100644 --- a/src/test/ui/coherence/coherence_inherent.re.stderr +++ b/src/test/ui/coherence/coherence_inherent.re.stderr @@ -5,7 +5,7 @@ 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: + = note: the following trait is implemented but not in scope, perhaps add a `use` for it: `use Lib::TheTrait;` error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_inherent_cc.old.stderr b/src/test/ui/coherence/coherence_inherent_cc.old.stderr index 3683943c5c819..59166a4609406 100644 --- a/src/test/ui/coherence/coherence_inherent_cc.old.stderr +++ b/src/test/ui/coherence/coherence_inherent_cc.old.stderr @@ -5,7 +5,7 @@ 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: + = note: the following trait is implemented but not in scope, perhaps add a `use` for it: `use coherence_inherent_cc_lib::TheTrait;` error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_inherent_cc.re.stderr b/src/test/ui/coherence/coherence_inherent_cc.re.stderr index 3683943c5c819..59166a4609406 100644 --- a/src/test/ui/coherence/coherence_inherent_cc.re.stderr +++ b/src/test/ui/coherence/coherence_inherent_cc.re.stderr @@ -5,7 +5,7 @@ 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: + = note: the following trait is implemented but not in scope, perhaps add a `use` for it: `use coherence_inherent_cc_lib::TheTrait;` error: aborting due to previous error diff --git a/src/test/ui/coherence/impl-foreign-for-foreign.rs b/src/test/ui/coherence/impl-foreign-for-foreign.rs deleted file mode 100644 index de0b66a35eb01..0000000000000 --- a/src/test/ui/coherence/impl-foreign-for-foreign.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote for i32 { - //~^ ERROR only traits defined in the current crate - // | can be implemented for arbitrary types [E0117] -} - -fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-foreign.stderr b/src/test/ui/coherence/impl-foreign-for-foreign.stderr deleted file mode 100644 index b03a75a77c346..0000000000000 --- a/src/test/ui/coherence/impl-foreign-for-foreign.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/impl-foreign-for-foreign.rs:12:1 - | -LL | impl Remote for i32 { - | ^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate - | - = note: the impl does not reference only types defined in this crate - = note: define and implement a trait or new type instead - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs deleted file mode 100644 index 5146263d99114..0000000000000 --- a/src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs +++ /dev/null @@ -1,25 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1> for i32 { - //~^ ERROR only traits defined in the current crate - // | can be implemented for arbitrary types [E0117] -} -impl Remote1> for f64 { - //~^ ERROR only traits defined in the current crate - // | can be implemented for arbitrary types [E0117] -} -impl Remote1> for f32 { - //~^ ERROR only traits defined in the current crate - // | can be implemented for arbitrary types [E0117] -} - -fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr deleted file mode 100644 index bfaec790b20a6..0000000000000 --- a/src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr +++ /dev/null @@ -1,30 +0,0 @@ -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/impl-foreign-for-foreign[foreign].rs:12:1 - | -LL | impl Remote1> for i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate - | - = note: the impl does not reference only types defined in this crate - = note: define and implement a trait or new type instead - -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/impl-foreign-for-foreign[foreign].rs:16:1 - | -LL | impl Remote1> for f64 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate - | - = note: the impl does not reference only types defined in this crate - = note: define and implement a trait or new type instead - -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/impl-foreign-for-foreign[foreign].rs:20:1 - | -LL | impl Remote1> for f32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate - | - = note: the impl does not reference only types defined in this crate - = note: define and implement a trait or new type instead - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl-foreign-for-foreign[local].rs b/src/test/ui/coherence/impl-foreign-for-foreign[local].rs deleted file mode 100644 index 050769dcf4ce8..0000000000000 --- a/src/test/ui/coherence/impl-foreign-for-foreign[local].rs +++ /dev/null @@ -1,16 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local(Rc); - -impl Remote1> for i32 {} -impl Remote1> for f32 {} - -fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs deleted file mode 100644 index 03b11edf98b41..0000000000000 --- a/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs +++ /dev/null @@ -1,21 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote for Box { - //~^ ERROR only traits defined in the current crate - // | can be implemented for arbitrary types [E0117] -} -impl Remote for Box> { - //~^ ERROR only traits defined in the current crate - // | can be implemented for arbitrary types [E0117] -} - -fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr deleted file mode 100644 index 2ce4921cf938f..0000000000000 --- a/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/impl-foreign-for-fundamental[foreign].rs:12:1 - | -LL | impl Remote for Box { - | ^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate - | - = note: the impl does not reference only types defined in this crate - = note: define and implement a trait or new type instead - -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/impl-foreign-for-fundamental[foreign].rs:16:1 - | -LL | impl Remote for Box> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate - | - = note: the impl does not reference only types defined in this crate - = note: define and implement a trait or new type instead - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[local].rs b/src/test/ui/coherence/impl-foreign-for-fundamental[local].rs deleted file mode 100644 index ae03ce6a440dc..0000000000000 --- a/src/test/ui/coherence/impl-foreign-for-fundamental[local].rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; -struct Local1(Rc); - -impl Remote for Box {} -impl Remote for Box> {} - -fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-local.rs b/src/test/ui/coherence/impl-foreign-for-local.rs deleted file mode 100644 index c9dddeba18dc5..0000000000000 --- a/src/test/ui/coherence/impl-foreign-for-local.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote for Local {} - -fn main() {} diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs deleted file mode 100644 index b08fedc5e11c2..0000000000000 --- a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1 for f64 { - //~^ ERROR only traits defined in the current crate - // | can be implemented for arbitrary types [E0117] -} - -fn main() {} diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr deleted file mode 100644 index 04e96f29230fb..0000000000000 --- a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/impl-foreign[foreign]-for-foreign.rs:12:1 - | -LL | impl Remote1 for f64 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate - | - = note: the impl does not reference only types defined in this crate - = note: define and implement a trait or new type instead - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-local.rs b/src/test/ui/coherence/impl-foreign[foreign]-for-local.rs deleted file mode 100644 index 33e85c164763e..0000000000000 --- a/src/test/ui/coherence/impl-foreign[foreign]-for-local.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1 for Local { -} - -fn main() {} diff --git a/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs deleted file mode 100644 index 06efb6c2ad75e..0000000000000 --- a/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; -struct Local1(Rc); - -impl Remote1> for i32 { - //~^ ERROR only traits defined in the current crate - // | can be implemented for arbitrary types [E0117] -} -impl Remote1>> for f64 { - //~^ ERROR only traits defined in the current crate - // | can be implemented for arbitrary types [E0117] -} -impl Remote1>> for f32 { - //~^ ERROR only traits defined in the current crate - // | can be implemented for arbitrary types [E0117] -} - -fn main() {} diff --git a/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr deleted file mode 100644 index bf2361a1718af..0000000000000 --- a/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:13:1 - | -LL | impl Remote1> for i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate - | - = note: the impl does not reference only types defined in this crate - = note: define and implement a trait or new type instead - -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:17:1 - | -LL | impl Remote1>> for f64 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate - | - = note: the impl does not reference only types defined in this crate - = note: define and implement a trait or new type instead - -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:21:1 - | -LL | impl Remote1>> for f32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate - | - = note: the impl does not reference only types defined in this crate - = note: define and implement a trait or new type instead - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs deleted file mode 100644 index d47e0a36a5659..0000000000000 --- a/src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; -struct Local1(Rc); - -impl Remote1> for i32 {} -impl Remote1>> for f64 {} -impl Remote1>> for f32 {} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs deleted file mode 100644 index db7a2ae8076a3..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs +++ /dev/null @@ -1,23 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; -use std::sync::Arc; - -struct Local; - -impl Remote for Rc { - //~^ ERROR only traits defined in the current crate - // | can be implemented for arbitrary types [E0117] -} - -impl Remote for Arc { - //~^ ERROR only traits defined in the current crate - // | can be implemented for arbitrary types [E0117] -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr deleted file mode 100644 index d7ffcaf76f9a2..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/impl[t]-foreign-for-foreign[t].rs:13:1 - | -LL | impl Remote for Rc { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate - | - = note: the impl does not reference only types defined in this crate - = note: define and implement a trait or new type instead - -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/impl[t]-foreign-for-foreign[t].rs:18:1 - | -LL | impl Remote for Arc { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate - | - = note: the impl does not reference only types defined in this crate - = note: define and implement a trait or new type instead - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs deleted file mode 100644 index 4cc19e1a526ca..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote for Box { - //~^ ERROR type parameter `T` must be used as the type parameter for - // | some local type (e.g., `MyStruct`) -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr deleted file mode 100644 index 20ce11ef9759e..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign-for-fundamental[t].rs:12:1 - | -LL | impl Remote for Box { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs deleted file mode 100644 index 54d4bf04a583c..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// check-pass -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; -impl Remote2, Local> for usize { } - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs deleted file mode 100644 index 66a4d9d273469..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs +++ /dev/null @@ -1,20 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1 for Box { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -impl<'a, T> Remote1 for &'a T { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr deleted file mode 100644 index 2467097b1a8b3..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[foreign]-for-fundamental[t].rs:12:1 - | -LL | impl Remote1 for Box { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[foreign]-for-fundamental[t].rs:16:1 - | -LL | impl<'a, T> Remote1 for &'a T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs deleted file mode 100644 index 0a67ebcbba44c..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1 for T { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr deleted file mode 100644 index 5c28406f113fc..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[foreign]-for-t.rs:12:1 - | -LL | impl Remote1 for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs deleted file mode 100644 index 71598dae96ab3..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1> for u32 { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -impl<'a, T> Remote1<&'a T> for u32 { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr deleted file mode 100644 index dd9702650795e..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[fundamental[t]]-for-foreign.rs:12:1 - | -LL | impl Remote1> for u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[fundamental[t]]-for-foreign.rs:16:1 - | -LL | impl<'a, T> Remote1<&'a T> for u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs deleted file mode 100644 index 7bf0306f29ba4..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs +++ /dev/null @@ -1,19 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl<'a, T> Remote1> for &'a T { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} -impl<'a, T> Remote1<&'a T> for Box { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr deleted file mode 100644 index eec57fccea762..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs:12:1 - | -LL | impl<'a, T> Remote1> for &'a T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs:15:1 - | -LL | impl<'a, T> Remote1<&'a T> for Box { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs deleted file mode 100644 index 54d577c749248..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1> for Local {} - -impl<'a, T> Remote1<&'a T> for Local {} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs deleted file mode 100644 index 7af929006ef7f..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1> for T { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} -impl<'a, T> Remote1<&'a T> for T { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr deleted file mode 100644 index e017c3ffe6c05..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[fundamental[t]]-for-t.rs:12:1 - | -LL | impl Remote1> for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[fundamental[t]]-for-t.rs:15:1 - | -LL | impl<'a, T> Remote1<&'a T> for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs deleted file mode 100644 index 24e0f309c4555..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote2, Local> for u32 { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -impl<'a, T> Remote2<&'a T, Local> for u32 { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr deleted file mode 100644 index 3d8561956ae7f..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:12:1 - | -LL | impl Remote2, Local> for u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:16:1 - | -LL | impl<'a, T> Remote2<&'a T, Local> for u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs b/src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs deleted file mode 100644 index 914680f191ac9..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; -struct Local1(Rc); - -impl Remote1> for Rc {} -impl Remote1>> for Rc {} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs deleted file mode 100644 index 81cf3c3f6eca9..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1 for Rc {} -impl Remote1 for Vec> {} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs deleted file mode 100644 index 1e84ff40c6227..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; -struct Local1(Rc); - -impl Remote1 for Rc {} -impl Remote1> for Rc {} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs deleted file mode 100644 index ea6aa101d209c..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs +++ /dev/null @@ -1,19 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; -struct Local1(Rc); - -impl Remote1 for Box> {} -impl Remote1> for Box> {} -impl Remote1> for Box> {} -impl Remote1>> for Box> {} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs deleted file mode 100644 index 54425b6d708aa..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs +++ /dev/null @@ -1,20 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1 for Box { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -impl Remote1 for &T { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr deleted file mode 100644 index 7859665a7bb58..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:12:1 - | -LL | impl Remote1 for Box { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:16:1 - | -LL | impl Remote1 for &T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs deleted file mode 100644 index 6b1d93cd94442..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1 for Local {} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs deleted file mode 100644 index 6f35c6c9dbc88..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1 for T { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr deleted file mode 100644 index be7de8cccb467..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[local]-for-t.rs:12:1 - | -LL | impl Remote1 for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs deleted file mode 100644 index be0875d0110fd..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; -struct Local2(Rc); - -impl Remote2> for u32 {} -impl<'a, T> Remote2 for u32 {} -impl Remote2, Box> for u32 {} -impl<'a, T> Remote2, &'a T> for u32 {} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs deleted file mode 100644 index 5e89c2077330a..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1 for u32 { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr deleted file mode 100644 index 5544729b5d640..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[t]-for-foreign.rs:12:1 - | -LL | impl Remote1 for u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs deleted file mode 100644 index 300a2c4d48a9c..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1 for Box { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -impl<'a, A, B> Remote1 for &'a B { - //~^ ERROR type parameter `B` must be used as the type parameter for some local type -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr deleted file mode 100644 index be8cc29a6e5b0..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[t]-for-fundamental.rs:12:1 - | -LL | impl Remote1 for Box { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error[E0210]: type parameter `B` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[t]-for-fundamental.rs:16:1 - | -LL | impl<'a, A, B> Remote1 for &'a B { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `B` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs deleted file mode 100644 index 769147ea7eabd..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs -// check-pass - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1 for Local {} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs deleted file mode 100644 index c8513380ff73e..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![feature(re_rebalance_coherence)] - -// compile-flags:--crate-name=test -// aux-build:coherence_lib.rs - -extern crate coherence_lib as lib; -use lib::*; -use std::rc::Rc; - -struct Local; - -impl Remote1 for T { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type -} - -fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr deleted file mode 100644 index de857afd20b15..0000000000000 --- a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[t]-for-t.rs:12:1 - | -LL | impl Remote1 for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type - | - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/re-rebalance-coherence-rpass.rs b/src/test/ui/coherence/re-rebalance-coherence-rpass.rs new file mode 100644 index 0000000000000..bacd3b89fad29 --- /dev/null +++ b/src/test/ui/coherence/re-rebalance-coherence-rpass.rs @@ -0,0 +1,14 @@ +#![allow(dead_code)] +#![feature(re_rebalance_coherence)] + +// run-pass +// aux-build:re_rebalance_coherence_lib.rs + +extern crate re_rebalance_coherence_lib as lib; +use lib::*; + +struct Oracle; +impl Backend for Oracle {} +impl<'a, T:'a, Tab> QueryFragment for BatchInsert<'a, T, Tab> {} + +fn main() {} diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr index 832f5c3ac2bb7..6b15b7ebbe9ee 100644 --- a/src/test/ui/conflicting-repr-hints.stderr +++ b/src/test/ui/conflicting-repr-hints.stderr @@ -66,4 +66,3 @@ LL | | } error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0566`. diff --git a/src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs b/src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs deleted file mode 100644 index 0aeba8607e818..0000000000000 --- a/src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs +++ /dev/null @@ -1,41 +0,0 @@ -// check-pass - -#![feature(array_value_iter)] -#![feature(trusted_len)] - -use std::{ - array::IntoIter, - fmt::Debug, - iter::{ExactSizeIterator, FusedIterator, TrustedLen}, -}; - -pub fn yes_iterator() -> impl Iterator { - IntoIter::new([0i32; 32]) -} - -pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator { - IntoIter::new([0i32; 32]) -} - -pub fn yes_exact_size_iterator() -> impl ExactSizeIterator { - IntoIter::new([0i32; 32]) -} - -pub fn yes_fused_iterator() -> impl FusedIterator { - IntoIter::new([0i32; 32]) -} - -pub fn yes_trusted_len() -> impl TrustedLen { - IntoIter::new([0i32; 32]) -} - -pub fn yes_clone() -> impl Clone { - IntoIter::new([0i32; 32]) -} - -pub fn yes_debug() -> impl Debug { - IntoIter::new([0i32; 32]) -} - - -fn main() {} diff --git a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.rs deleted file mode 100644 index a0bbd2ce64add..0000000000000 --- a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.rs +++ /dev/null @@ -1,53 +0,0 @@ -#![feature(array_value_iter)] -#![feature(trusted_len)] - -use std::{ - array::IntoIter, - fmt::Debug, - iter::{ExactSizeIterator, FusedIterator, TrustedLen}, -}; - -pub fn no_iterator() -> impl Iterator { - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 - IntoIter::new([0i32; 33]) - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 -} - -pub fn no_double_ended_iterator() -> impl DoubleEndedIterator { - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 - IntoIter::new([0i32; 33]) - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 -} - -pub fn no_exact_size_iterator() -> impl ExactSizeIterator { - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 - IntoIter::new([0i32; 33]) - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 -} - -pub fn no_fused_iterator() -> impl FusedIterator { - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 - IntoIter::new([0i32; 33]) - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 -} - -pub fn no_trusted_len() -> impl TrustedLen { - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 - IntoIter::new([0i32; 33]) - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 -} - -pub fn no_clone() -> impl Clone { - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 - IntoIter::new([0i32; 33]) - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 -} - -pub fn no_debug() -> impl Debug { - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 - IntoIter::new([0i32; 33]) - //~^ ERROR arrays only have std trait implementations for lengths 0..=32 -} - - -fn main() {} diff --git a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr deleted file mode 100644 index bfdff8e3bbe61..0000000000000 --- a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr +++ /dev/null @@ -1,122 +0,0 @@ -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:12:5 - | -LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required by `std::array::IntoIter::::new` - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:10:25 - | -LL | pub fn no_iterator() -> impl Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::array::IntoIter` - = note: the return type of a function must have a statically known size - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:18:5 - | -LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required by `std::array::IntoIter::::new` - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:16:38 - | -LL | pub fn no_double_ended_iterator() -> impl DoubleEndedIterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::array::IntoIter` - = note: the return type of a function must have a statically known size - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:24:5 - | -LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required by `std::array::IntoIter::::new` - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:22:36 - | -LL | pub fn no_exact_size_iterator() -> impl ExactSizeIterator { - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required because of the requirements on the impl of `std::iter::ExactSizeIterator` for `std::array::IntoIter` - = note: the return type of a function must have a statically known size - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:30:5 - | -LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required by `std::array::IntoIter::::new` - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:28:31 - | -LL | pub fn no_fused_iterator() -> impl FusedIterator { - | ^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required because of the requirements on the impl of `std::iter::FusedIterator` for `std::array::IntoIter` - = note: the return type of a function must have a statically known size - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:36:5 - | -LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required by `std::array::IntoIter::::new` - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:34:28 - | -LL | pub fn no_trusted_len() -> impl TrustedLen { - | ^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required because of the requirements on the impl of `std::iter::TrustedLen` for `std::array::IntoIter` - = note: the return type of a function must have a statically known size - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:42:5 - | -LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required by `std::array::IntoIter::::new` - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:40:22 - | -LL | pub fn no_clone() -> impl Clone { - | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required because of the requirements on the impl of `std::clone::Clone` for `std::array::IntoIter` - = note: the return type of a function must have a statically known size - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:48:5 - | -LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required by `std::array::IntoIter::::new` - -error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:46:22 - | -LL | pub fn no_debug() -> impl Debug { - | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` - | - = note: required because of the requirements on the impl of `std::fmt::Debug` for `std::array::IntoIter` - = note: the return type of a function must have a statically known size - -error: aborting due to 14 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/auxiliary/const_generic_lib.rs b/src/test/ui/const-generics/auxiliary/const_generic_lib.rs deleted file mode 100644 index 901fb5dd054e2..0000000000000 --- a/src/test/ui/const-generics/auxiliary/const_generic_lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(const_generics)] - -pub struct Struct(pub [u8; N]); - -pub type Alias = Struct<2>; - -pub fn function(value: Struct<3>) -> u8 { - value.0[0] -} diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs deleted file mode 100644 index d863d097d5caf..0000000000000 --- a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs +++ /dev/null @@ -1,10 +0,0 @@ -// aux-build:const_generic_lib.rs - -extern crate const_generic_lib; - -fn main() { - let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8])); - //~^ ERROR mismatched types - let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]); - //~^ ERROR mismatched types -} diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr deleted file mode 100644 index 7090cb880fd49..0000000000000 --- a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/const-argument-cross-crate-mismatch.rs:6:67 - | -LL | let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8])); - | ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements - | - = note: expected type `[u8; 3]` - found type `[u8; 2]` - -error[E0308]: mismatched types - --> $DIR/const-argument-cross-crate-mismatch.rs:8:65 - | -LL | let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]); - | ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements - | - = note: expected type `[u8; 2]` - found type `[u8; 3]` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/const-argument-cross-crate.rs b/src/test/ui/const-generics/const-argument-cross-crate.rs deleted file mode 100644 index 98cf39a7ee11c..0000000000000 --- a/src/test/ui/const-generics/const-argument-cross-crate.rs +++ /dev/null @@ -1,12 +0,0 @@ -// run-pass -// aux-build:const_generic_lib.rs - -extern crate const_generic_lib; - -struct Container(const_generic_lib::Alias); - -fn main() { - let res = const_generic_lib::function(const_generic_lib::Struct([14u8, 1u8, 2u8])); - assert_eq!(res, 14u8); - let _ = Container(const_generic_lib::Struct([0u8, 1u8])); -} diff --git a/src/test/ui/const-generics/const-param-in-trait-ungated.stderr b/src/test/ui/const-generics/const-param-in-trait-ungated.stderr index 330c93e83b5e7..cfb1f8b581c85 100644 --- a/src/test/ui/const-generics/const-param-in-trait-ungated.stderr +++ b/src/test/ui/const-generics/const-param-in-trait-ungated.stderr @@ -1,8 +1,8 @@ error[E0658]: const generics are unstable - --> $DIR/const-param-in-trait-ungated.rs:1:13 + --> $DIR/const-param-in-trait-ungated.rs:1:19 | LL | trait Trait {} - | ^^^^^^^^^^^ + | ^ | = note: for more information, see https://github.com/rust-lang/rust/issues/44580 = help: add `#![feature(const_generics)]` to the crate attributes to enable diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs index 78bd549ba791a..af5e8f49754e8 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; struct B(PhantomData<[T; N]>); //~ ERROR const generics are unstable -//~^ ERROR the types of const generic parameters must derive `PartialEq` and `Eq` +//~^ ERROR const parameters cannot depend on type parameters fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr index e34a2da24cecc..c659074a091c8 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr @@ -1,19 +1,19 @@ +error[E0671]: const parameters cannot depend on type parameters + --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22 + | +LL | struct B(PhantomData<[T; N]>); + | ^ const parameter depends on type parameter + error[E0658]: const generics are unstable - --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:13 + --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19 | LL | struct B(PhantomData<[T; N]>); - | ^^^^^^^^^^ + | ^ | = note: for more information, see https://github.com/rust-lang/rust/issues/44580 = help: add `#![feature(const_generics)]` to the crate attributes to enable -error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq` - --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22 - | -LL | struct B(PhantomData<[T; N]>); - | ^ `T` doesn't derive both `PartialEq` and `Eq` - error: aborting due to 2 previous errors -Some errors have detailed explanations: E0658, E0741. +Some errors have detailed explanations: E0658, E0671. For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs index b76209571b05c..28e0d6c2bb7e7 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs @@ -7,6 +7,7 @@ // details. pub struct Dependent([(); X]); -//~^ ERROR the types of const generic parameters must derive `PartialEq` and `Eq` +//~^ ERROR const parameters cannot depend on type parameters +//~^^ ERROR parameter `T` is never used fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr index c9d6db7e2c220..142efe45ac2d7 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr @@ -1,3 +1,9 @@ +error[E0671]: const parameters cannot depend on type parameters + --> $DIR/const-param-type-depends-on-type-param.rs:9:34 + | +LL | pub struct Dependent([(); X]); + | ^ const parameter depends on type parameter + warning: the feature `const_generics` is incomplete and may cause the compiler to crash --> $DIR/const-param-type-depends-on-type-param.rs:1:12 | @@ -6,12 +12,15 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq` - --> $DIR/const-param-type-depends-on-type-param.rs:9:34 +error[E0392]: parameter `T` is never used + --> $DIR/const-param-type-depends-on-type-param.rs:9:22 | LL | pub struct Dependent([(); X]); - | ^ `T` doesn't derive both `PartialEq` and `Eq` + | ^ unused parameter + | + = help: consider removing `T` or using a marker such as `std::marker::PhantomData` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0741`. +Some errors have detailed explanations: E0392, E0671. +For more information about an error, try `rustc --explain E0392`. diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr index 32cf8d8a01a78..fddb06981bc73 100644 --- a/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr +++ b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr @@ -10,7 +10,7 @@ error: const parameter `x` should have an upper case name --> $DIR/const-parameter-uppercase-lint.rs:6:15 | LL | fn noop() { - | ^ help: convert the identifier to upper case (notice the capitalization): `X` + | ^ help: convert the identifier to upper case: `X` | note: lint level defined here --> $DIR/const-parameter-uppercase-lint.rs:4:9 diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs deleted file mode 100644 index 84615386d2995..0000000000000 --- a/src/test/ui/const-generics/fn-const-param-call.rs +++ /dev/null @@ -1,20 +0,0 @@ -// run-pass - -#![feature(const_generics, const_compare_raw_pointers)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -fn function() -> u32 { - 17 -} - -struct Wrapper u32>; - -impl u32> Wrapper<{F}> { - fn call() -> u32 { - F() - } -} - -fn main() { - assert_eq!(Wrapper::<{function}>::call(), 17); -} diff --git a/src/test/ui/const-generics/fn-const-param-call.stderr b/src/test/ui/const-generics/fn-const-param-call.stderr deleted file mode 100644 index c677d70374931..0000000000000 --- a/src/test/ui/const-generics/fn-const-param-call.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/fn-const-param-call.rs:3:12 - | -LL | #![feature(const_generics, const_compare_raw_pointers)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs deleted file mode 100644 index 78fb10e8cb904..0000000000000 --- a/src/test/ui/const-generics/fn-const-param-infer.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![feature(const_generics, const_compare_raw_pointers)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -struct Checked bool>; - -fn not_one(val: usize) -> bool { val != 1 } -fn not_two(val: usize) -> bool { val != 2 } - -fn generic_arg(val: T) -> bool { true } - -fn generic(val: usize) -> bool { val != 1 } - -fn main() { - let _: Option> = None; - let _: Checked<{not_one}> = Checked::<{not_one}>; - let _: Checked<{not_one}> = Checked::<{not_two}>; //~ mismatched types - - let _ = Checked::<{generic_arg}>; - let _ = Checked::<{generic_arg::}>; - let _ = Checked::<{generic_arg::}>; //~ mismatched types - - let _ = Checked::<{generic}>; //~ type annotations needed - let _ = Checked::<{generic::}>; - let _: Checked<{generic::}> = Checked::<{generic::}>; - let _: Checked<{generic::}> = Checked::<{generic::}>; //~ mismatched types -} diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr deleted file mode 100644 index de0916b26bfef..0000000000000 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ /dev/null @@ -1,45 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/fn-const-param-infer.rs:1:12 - | -LL | #![feature(const_generics, const_compare_raw_pointers)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error[E0308]: mismatched types - --> $DIR/fn-const-param-infer.rs:16:33 - | -LL | let _: Checked<{not_one}> = Checked::<{not_two}>; - | ^^^^^^^^^^^^^^^^^^^^ expected `not_one`, found `not_two` - | - = note: expected type `Checked` - found type `Checked` - -error[E0308]: mismatched types - --> $DIR/fn-const-param-infer.rs:20:24 - | -LL | let _ = Checked::<{generic_arg::}>; - | ^^^^^^^^^^^^^^^^^^ expected usize, found u32 - | - = note: expected type `fn(usize) -> bool` - found type `fn(u32) -> bool {generic_arg::}` - -error[E0282]: type annotations needed - --> $DIR/fn-const-param-infer.rs:22:24 - | -LL | let _ = Checked::<{generic}>; - | ^^^^^^^ cannot infer type for `T` - -error[E0308]: mismatched types - --> $DIR/fn-const-param-infer.rs:25:40 - | -LL | let _: Checked<{generic::}> = Checked::<{generic::}>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `generic::`, found `generic::` - | - = note: expected type `Checked>` - found type `Checked>` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0282, E0308. -For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.rs b/src/test/ui/const-generics/forbid-non-structural_match-types.rs deleted file mode 100644 index 7bc4f3986eb75..0000000000000 --- a/src/test/ui/const-generics/forbid-non-structural_match-types.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -#[derive(PartialEq, Eq)] -struct A; - -struct B; // ok - -struct C; - -struct D; //~ ERROR the types of const generic parameters must derive - -fn main() {} diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr deleted file mode 100644 index 0fd9e0599e80e..0000000000000 --- a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/forbid-non-structural_match-types.rs:1:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq` - --> $DIR/forbid-non-structural_match-types.rs:11:19 - | -LL | struct D; - | ^ `C` doesn't derive both `PartialEq` and `Eq` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0741`. diff --git a/src/test/ui/const-generics/issues/issue-60263.rs b/src/test/ui/const-generics/issue-60263.rs similarity index 100% rename from src/test/ui/const-generics/issues/issue-60263.rs rename to src/test/ui/const-generics/issue-60263.rs diff --git a/src/test/ui/const-generics/issues/issue-60263.stderr b/src/test/ui/const-generics/issue-60263.stderr similarity index 86% rename from src/test/ui/const-generics/issues/issue-60263.stderr rename to src/test/ui/const-generics/issue-60263.stderr index 5223c8c5137ae..fe7b6fdb1904d 100644 --- a/src/test/ui/const-generics/issues/issue-60263.stderr +++ b/src/test/ui/const-generics/issue-60263.stderr @@ -1,8 +1,8 @@ error[E0658]: const generics are unstable - --> $DIR/issue-60263.rs:1:10 + --> $DIR/issue-60263.rs:1:16 | LL | struct B; - | ^^^^^^^^^^^ + | ^ | = note: for more information, see https://github.com/rust-lang/rust/issues/44580 = help: add `#![feature(const_generics)]` to the crate attributes to enable diff --git a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs b/src/test/ui/const-generics/issue-60818-struct-constructors.rs similarity index 100% rename from src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs rename to src/test/ui/const-generics/issue-60818-struct-constructors.rs diff --git a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr b/src/test/ui/const-generics/issue-60818-struct-constructors.stderr similarity index 100% rename from src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr rename to src/test/ui/const-generics/issue-60818-struct-constructors.stderr diff --git a/src/test/ui/const-generics/issues/issue-61336-1.rs b/src/test/ui/const-generics/issue-61336-1.rs similarity index 100% rename from src/test/ui/const-generics/issues/issue-61336-1.rs rename to src/test/ui/const-generics/issue-61336-1.rs diff --git a/src/test/ui/const-generics/issues/issue-61336-1.stderr b/src/test/ui/const-generics/issue-61336-1.stderr similarity index 100% rename from src/test/ui/const-generics/issues/issue-61336-1.stderr rename to src/test/ui/const-generics/issue-61336-1.stderr diff --git a/src/test/ui/const-generics/issues/issue-61336-2.rs b/src/test/ui/const-generics/issue-61336-2.rs similarity index 100% rename from src/test/ui/const-generics/issues/issue-61336-2.rs rename to src/test/ui/const-generics/issue-61336-2.rs diff --git a/src/test/ui/const-generics/issues/issue-61336-2.stderr b/src/test/ui/const-generics/issue-61336-2.stderr similarity index 100% rename from src/test/ui/const-generics/issues/issue-61336-2.stderr rename to src/test/ui/const-generics/issue-61336-2.stderr diff --git a/src/test/ui/const-generics/issues/issue-61336.rs b/src/test/ui/const-generics/issue-61336.rs similarity index 100% rename from src/test/ui/const-generics/issues/issue-61336.rs rename to src/test/ui/const-generics/issue-61336.rs diff --git a/src/test/ui/const-generics/issues/issue-61336.stderr b/src/test/ui/const-generics/issue-61336.stderr similarity index 100% rename from src/test/ui/const-generics/issues/issue-61336.stderr rename to src/test/ui/const-generics/issue-61336.stderr diff --git a/src/test/ui/const-generics/issues/issue-61422.rs b/src/test/ui/const-generics/issue-61422.rs similarity index 100% rename from src/test/ui/const-generics/issues/issue-61422.rs rename to src/test/ui/const-generics/issue-61422.rs diff --git a/src/test/ui/const-generics/issues/issue-61422.stderr b/src/test/ui/const-generics/issue-61422.stderr similarity index 100% rename from src/test/ui/const-generics/issues/issue-61422.stderr rename to src/test/ui/const-generics/issue-61422.stderr diff --git a/src/test/ui/const-generics/issues/issue-61432.rs b/src/test/ui/const-generics/issue-61432.rs similarity index 100% rename from src/test/ui/const-generics/issues/issue-61432.rs rename to src/test/ui/const-generics/issue-61432.rs diff --git a/src/test/ui/const-generics/issues/issue-61432.stderr b/src/test/ui/const-generics/issue-61432.stderr similarity index 100% rename from src/test/ui/const-generics/issues/issue-61432.stderr rename to src/test/ui/const-generics/issue-61432.stderr diff --git a/src/test/ui/const-generics/issues/issue-64519.rs b/src/test/ui/const-generics/issue-64519.rs similarity index 100% rename from src/test/ui/const-generics/issues/issue-64519.rs rename to src/test/ui/const-generics/issue-64519.rs diff --git a/src/test/ui/const-generics/issues/issue-64519.stderr b/src/test/ui/const-generics/issue-64519.stderr similarity index 100% rename from src/test/ui/const-generics/issues/issue-64519.stderr rename to src/test/ui/const-generics/issue-64519.stderr diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs deleted file mode 100644 index 4dc46eb0ef65a..0000000000000 --- a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs +++ /dev/null @@ -1,16 +0,0 @@ -// run-pass - -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -pub trait BitLen: Sized { - const BIT_LEN: usize; -} - -impl BitLen for [u8; L] { - const BIT_LEN: usize = 8 * L; -} - -fn main() { - let foo = <[u8; 2]>::BIT_LEN; -} diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr deleted file mode 100644 index 20347ac4b7dac..0000000000000 --- a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr +++ /dev/null @@ -1,16 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/issue-62187-encountered-polymorphic-const.rs:3:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -warning: unused variable: `foo` - --> $DIR/issue-62187-encountered-polymorphic-const.rs:15:9 - | -LL | let foo = <[u8; 2]>::BIT_LEN; - | ^^^ help: consider prefixing with an underscore: `_foo` - | - = note: `#[warn(unused_variables)]` on by default - diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.rs b/src/test/ui/const-generics/issues/issue-62579-no-match.rs deleted file mode 100644 index 0ff7ddc41fe4c..0000000000000 --- a/src/test/ui/const-generics/issues/issue-62579-no-match.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass - -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -#[derive(PartialEq, Eq)] -struct NoMatch; - -fn foo() -> bool { - true -} - -fn main() { - foo::<{NoMatch}>(); -} diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.stderr deleted file mode 100644 index 759d5fdeb4c16..0000000000000 --- a/src/test/ui/const-generics/issues/issue-62579-no-match.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/issue-62579-no-match.rs:3:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - diff --git a/src/test/ui/const-generics/issues/issue-65675.rs b/src/test/ui/const-generics/issues/issue-65675.rs deleted file mode 100644 index 3ca527313f93f..0000000000000 --- a/src/test/ui/const-generics/issues/issue-65675.rs +++ /dev/null @@ -1,10 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -pub struct Foo([T; N]); -impl Foo {} - -fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-65675.stderr b/src/test/ui/const-generics/issues/issue-65675.stderr deleted file mode 100644 index 60b388e62783e..0000000000000 --- a/src/test/ui/const-generics/issues/issue-65675.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/issue-65675.rs:4:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs deleted file mode 100644 index d26ab8be4c3fe..0000000000000 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs +++ /dev/null @@ -1,19 +0,0 @@ -// run-pass -#![feature(const_generics, const_compare_raw_pointers)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -const A: u32 = 3; - -struct Const; - -impl Const<{P}> { - fn get() -> u32 { - unsafe { - *P - } - } -} - -fn main() { - assert_eq!(Const::<{&A as *const _}>::get(), 3) -} diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr deleted file mode 100644 index 73221596c8e87..0000000000000 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/raw-ptr-const-param-deref.rs:2:12 - | -LL | #![feature(const_generics, const_compare_raw_pointers)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs deleted file mode 100644 index f69c37fbb8f3d..0000000000000 --- a/src/test/ui/const-generics/raw-ptr-const-param.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(const_generics, const_compare_raw_pointers)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -struct Const; - -fn main() { - let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; //~ mismatched types - let _: Const<{10 as *const _}> = Const::<{10 as *const _}>; -} diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr deleted file mode 100644 index 75b4c0a0a3de3..0000000000000 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ /dev/null @@ -1,20 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/raw-ptr-const-param.rs:1:12 - | -LL | #![feature(const_generics, const_compare_raw_pointers)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error[E0308]: mismatched types - --> $DIR/raw-ptr-const-param.rs:7:38 - | -LL | let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{pointer}`, found `{pointer}` - | - = note: expected type `Const<{pointer}>` - found type `Const<{pointer}>` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.rs b/src/test/ui/const-generics/slice-const-param-mismatch.rs deleted file mode 100644 index 73c75ae666805..0000000000000 --- a/src/test/ui/const-generics/slice-const-param-mismatch.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -struct ConstString; -struct ConstBytes; - -pub fn main() { - let _: ConstString<"Hello"> = ConstString::<"Hello">; - let _: ConstString<"Hello"> = ConstString::<"World">; //~ ERROR mismatched types - let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↦">; - let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; //~ ERROR mismatched types - let _: ConstBytes = ConstBytes::<{&[0x41, 0x41, 0x41]}>; - let _: ConstBytes = ConstBytes::; //~ ERROR mismatched types -} diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.stderr deleted file mode 100644 index 380a70d664e05..0000000000000 --- a/src/test/ui/const-generics/slice-const-param-mismatch.stderr +++ /dev/null @@ -1,38 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/slice-const-param-mismatch.rs:1:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error[E0308]: mismatched types - --> $DIR/slice-const-param-mismatch.rs:9:35 - | -LL | let _: ConstString<"Hello"> = ConstString::<"World">; - | ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"` - | - = note: expected type `ConstString<"Hello">` - found type `ConstString<"World">` - -error[E0308]: mismatched types - --> $DIR/slice-const-param-mismatch.rs:11:33 - | -LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; - | ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"` - | - = note: expected type `ConstString<"ℇ㇈↦">` - found type `ConstString<"ℇ㇈↥">` - -error[E0308]: mismatched types - --> $DIR/slice-const-param-mismatch.rs:13:33 - | -LL | let _: ConstBytes = ConstBytes::; - | ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"` - | - = note: expected type `ConstBytes` - found type `ConstBytes` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/slice-const-param.rs b/src/test/ui/const-generics/slice-const-param.rs deleted file mode 100644 index 2629caa392106..0000000000000 --- a/src/test/ui/const-generics/slice-const-param.rs +++ /dev/null @@ -1,19 +0,0 @@ -// run-pass - -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -pub fn function_with_str() -> &'static str { - STRING -} - -pub fn function_with_bytes() -> &'static [u8] { - BYTES -} - -pub fn main() { - assert_eq!(function_with_str::<"Rust">(), "Rust"); - assert_eq!(function_with_str::<"ℇ㇈↦">(), "ℇ㇈↦"); - assert_eq!(function_with_bytes::(), &[0x41, 0x41, 0x41, 0x41]); - assert_eq!(function_with_bytes::<{&[0x41, 0x41, 0x41, 0x41]}>(), b"AAAA"); -} diff --git a/src/test/ui/const-generics/slice-const-param.stderr b/src/test/ui/const-generics/slice-const-param.stderr deleted file mode 100644 index 79214a34fdba0..0000000000000 --- a/src/test/ui/const-generics/slice-const-param.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/slice-const-param.rs:3:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr index b3aa35e079aec..dfa2557e9f6f8 100644 --- a/src/test/ui/const-generics/struct-with-invalid-const-param.stderr +++ b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr @@ -14,4 +14,3 @@ LL | #![feature(const_generics)] error: aborting due to previous error -For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/const-generics/types-mismatch-const-args.rs b/src/test/ui/const-generics/types-mismatch-const-args.rs deleted file mode 100644 index b25b7331017e7..0000000000000 --- a/src/test/ui/const-generics/types-mismatch-const-args.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -// tests the diagnostic output of type mismatches for types that have const generics arguments. - -use std::marker::PhantomData; - -struct A<'a, T, const X: u32, const Y: u32> { - data: PhantomData<&'a T> -} - -fn a<'a, 'b>() { - let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData }; - //~^ ERROR mismatched types - let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; - //~^ ERROR mismatched types -} - -pub fn main() {} diff --git a/src/test/ui/const-generics/types-mismatch-const-args.stderr b/src/test/ui/const-generics/types-mismatch-const-args.stderr deleted file mode 100644 index 805a3067d3b6b..0000000000000 --- a/src/test/ui/const-generics/types-mismatch-const-args.stderr +++ /dev/null @@ -1,29 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/types-mismatch-const-args.rs:1:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error[E0308]: mismatched types - --> $DIR/types-mismatch-const-args.rs:13:41 - | -LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2u32`, found `4u32` - | - = note: expected type `A<'_, _, 2u32, _>` - found type `A<'_, _, 4u32, _>` - -error[E0308]: mismatched types - --> $DIR/types-mismatch-const-args.rs:15:41 - | -LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u16, found u32 - | - = note: expected type `A<'a, u16, _, _>` - found type `A<'b, u32, _, _>` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/consts/auxiliary/external_macro.rs b/src/test/ui/consts/auxiliary/external_macro.rs deleted file mode 100644 index d260634c9963b..0000000000000 --- a/src/test/ui/consts/auxiliary/external_macro.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(allow_internal_unstable)] - -// Macro to help ensure CONST_ERR lint errors -// are not silenced in external macros. -// https://github.com/rust-lang/rust/issues/65300 - -#[macro_export] -#[allow_internal_unstable(type_ascription)] -macro_rules! static_assert { - ($test:expr) => { - #[allow(dead_code)] - const _: () = [()][!($test: bool) as usize]; - } -} diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index e5ee90fc9f11f..ecbcc2a4b496f 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -23,7 +23,6 @@ fn main() { //~^ ERROR const_err let _e = [5u8][1]; //~^ ERROR index out of bounds - //~| ERROR this expression will panic at runtime 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 0a09a7213dabc..1d84d44dc27b3 100644 --- a/src/test/ui/consts/const-err2.stderr +++ b/src/test/ui/consts/const-err2.stderr @@ -34,11 +34,5 @@ error: index out of bounds: the len is 1 but the index is 1 LL | let _e = [5u8][1]; | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/const-err2.rs:24:14 - | -LL | let _e = [5u8][1]; - | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/consts/const-err3.rs b/src/test/ui/consts/const-err3.rs index 89373f99f75c2..a9cf04cda7a5a 100644 --- a/src/test/ui/consts/const-err3.rs +++ b/src/test/ui/consts/const-err3.rs @@ -23,7 +23,6 @@ fn main() { //~^ ERROR const_err let _e = [5u8][1]; //~^ ERROR const_err - //~| ERROR this expression will panic at runtime black_box(a); black_box(b); black_box(c); diff --git a/src/test/ui/consts/const-err3.stderr b/src/test/ui/consts/const-err3.stderr index 42de247c8f7e0..0602707be7040 100644 --- a/src/test/ui/consts/const-err3.stderr +++ b/src/test/ui/consts/const-err3.stderr @@ -34,11 +34,5 @@ error: index out of bounds: the len is 1 but the index is 1 LL | let _e = [5u8][1]; | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/const-err3.rs:24:14 - | -LL | let _e = [5u8][1]; - | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/consts/const-eval/const_let.stderr b/src/test/ui/consts/const-eval/const_let.stderr index 4753222a7c07d..0a6a222ae2963 100644 --- a/src/test/ui/consts/const-eval/const_let.stderr +++ b/src/test/ui/consts/const-eval/const_let.stderr @@ -24,4 +24,3 @@ LL | const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); }; error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/const-eval/generic-slice.rs b/src/test/ui/consts/const-eval/generic-slice.rs deleted file mode 100644 index 21360a1c471f6..0000000000000 --- a/src/test/ui/consts/const-eval/generic-slice.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Several variants of #64945. - -// This struct is not important, we just use it to put `T` and `'a` in scope for our associated -// consts. -struct Generic<'a, T>(std::marker::PhantomData<&'a T>); - -impl<'a, T: 'static> Generic<'a, T> { - const EMPTY_SLICE: &'a [T] = { - let x: &'a [T] = &[]; - x - }; - - const EMPTY_SLICE_REF: &'a &'static [T] = { - let x: &'static [T] = &[]; - &x - //~^ ERROR `x` does not live long enough - }; -} - -static mut INTERIOR_MUT_AND_DROP: &'static [std::cell::RefCell>] = { - let x: &[_] = &[]; - x -}; - -static mut INTERIOR_MUT_AND_DROP_REF: &'static &'static [std::cell::RefCell>] = { - let x: &[_] = &[]; - &x - //~^ ERROR `x` does not live long enough -}; - -fn main() {} diff --git a/src/test/ui/consts/const-eval/generic-slice.stderr b/src/test/ui/consts/const-eval/generic-slice.stderr deleted file mode 100644 index c38088df4d8e6..0000000000000 --- a/src/test/ui/consts/const-eval/generic-slice.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error[E0597]: `x` does not live long enough - --> $DIR/generic-slice.rs:15:9 - | -LL | impl<'a, T: 'static> Generic<'a, T> { - | -- lifetime `'a` defined here -... -LL | &x - | ^^ - | | - | borrowed value does not live long enough - | using this value as a constant requires that `x` is borrowed for `'a` -LL | -LL | }; - | - `x` dropped here while still borrowed - -error[E0597]: `x` does not live long enough - --> $DIR/generic-slice.rs:27:5 - | -LL | &x - | ^^ - | | - | borrowed value does not live long enough - | using this value as a static requires that `x` is borrowed for `'static` -LL | -LL | }; - | - `x` dropped here while still borrowed - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs index b85cecda16e95..274967ef60de5 100644 --- a/src/test/ui/consts/const-eval/issue-50814.rs +++ b/src/test/ui/consts/const-eval/issue-50814.rs @@ -11,6 +11,7 @@ struct Sum(A,B); impl Unsigned for Sum { const MAX: u8 = A::MAX + B::MAX; //~ ERROR any use of this value will cause an error + //~| ERROR any use of this value will cause an error } fn foo(_: T) -> &'static u8 { diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr index 707dfee7cd5b8..de3459c72dd2b 100644 --- a/src/test/ui/consts/const-eval/issue-50814.stderr +++ b/src/test/ui/consts/const-eval/issue-50814.stderr @@ -9,13 +9,21 @@ LL | const MAX: u8 = A::MAX + B::MAX; = note: `#[deny(const_err)]` on by default error[E0080]: evaluation of constant expression failed - --> $DIR/issue-50814.rs:17:5 + --> $DIR/issue-50814.rs:18:5 | LL | &Sum::::MAX | ^----------------- | | | referenced constant has errors -error: aborting due to 2 previous errors +error: any use of this value will cause an error + --> $DIR/issue-50814.rs:13:21 + | +LL | const MAX: u8 = A::MAX + B::MAX; + | ----------------^^^^^^^^^^^^^^^- + | | + | attempt to add with overflow + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/issue-64908.rs b/src/test/ui/consts/const-eval/issue-64908.rs deleted file mode 100644 index d2e095072844f..0000000000000 --- a/src/test/ui/consts/const-eval/issue-64908.rs +++ /dev/null @@ -1,20 +0,0 @@ -// run-pass - -// This test verifies that the `ConstProp` pass doesn't cause an ICE when evaluating polymorphic -// promoted MIR. - -pub trait ArrowPrimitiveType { - type Native; -} - -pub fn new() { - assert_eq!(0, std::mem::size_of::()); -} - -impl ArrowPrimitiveType for () { - type Native = (); -} - -fn main() { - new::<()>(); -} diff --git a/src/test/ui/consts/const-eval/issue-64970.rs b/src/test/ui/consts/const-eval/issue-64970.rs deleted file mode 100644 index ede5081c8a5c2..0000000000000 --- a/src/test/ui/consts/const-eval/issue-64970.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass - -fn main() { - foo(10); -} - -fn foo(mut n: i32) { - if false { - n = 0i32; - } - - if n > 0i32 { - 1i32 / n; - } -} diff --git a/src/test/ui/consts/const-eval/issue-64970.stderr b/src/test/ui/consts/const-eval/issue-64970.stderr deleted file mode 100644 index 2c44b68cbd1d1..0000000000000 --- a/src/test/ui/consts/const-eval/issue-64970.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unused arithmetic operation that must be used - --> $DIR/issue-64970.rs:13:9 - | -LL | 1i32 / n; - | ^^^^^^^^ - | - = note: `#[warn(unused_must_use)]` on by default - diff --git a/src/test/ui/consts/const-eval/issue-65394.rs b/src/test/ui/consts/const-eval/issue-65394.rs deleted file mode 100644 index 8cf527f0429f0..0000000000000 --- a/src/test/ui/consts/const-eval/issue-65394.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Test for absence of validation mismatch ICE in #65394 - -const _: Vec = { - let mut x = Vec::::new(); - let r = &mut x; //~ ERROR references in constants may only refer to immutable values - let y = x; - y -}; - -fn main() {} diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr deleted file mode 100644 index 15df813836e5b..0000000000000 --- a/src/test/ui/consts/const-eval/issue-65394.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0017]: references in constants may only refer to immutable values - --> $DIR/issue-65394.rs:5:13 - | -LL | let r = &mut x; - | ^^^^^^ constants require immutable values - -[ERROR rustc_mir::transform::qualify_consts] old validator: [($DIR/issue-65394.rs:5:13: 5:19, "MutBorrow(Mut { allow_two_phase_borrow: false })")] -[ERROR rustc_mir::transform::qualify_consts] new validator: [($DIR/issue-65394.rs:5:13: 5:19, "MutBorrow(Mut { allow_two_phase_borrow: false })"), ($DIR/issue-65394.rs:4:9: 4:14, "LiveDrop")] -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0017`. diff --git a/src/test/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs b/src/test/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs deleted file mode 100644 index cccb7879fc0fb..0000000000000 --- a/src/test/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs +++ /dev/null @@ -1,28 +0,0 @@ -// run-pass - -#![allow(dead_code)] - -enum Empty { } -enum Test1 { - A(u8), - B(Empty), -} -enum Test2 { - A(u8), - B(Empty), - C, -} - -fn bar() -> Option { - None -} - -fn main() { - if let Some(x) = bar() { - Test1::B(x); - } - - if let Some(x) = bar() { - Test2::B(x); - } -} diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs deleted file mode 100644 index 7c6a574a2110f..0000000000000 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs +++ /dev/null @@ -1,23 +0,0 @@ -#![feature(const_extern_fn)] - -extern "C" { - fn regular_in_block(); -} - -const extern fn bar() { - unsafe { - regular_in_block(); - //~^ ERROR: cannot call functions with `"C"` abi in `min_const_fn` - } -} - -extern fn regular() {} - -const extern fn foo() { - unsafe { - regular(); - //~^ ERROR: cannot call functions with `"C"` abi in `min_const_fn` - } -} - -fn main() {} diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr deleted file mode 100644 index d8bdf0a57cf66..0000000000000 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0723]: cannot call functions with `"C"` abi in `min_const_fn` - --> $DIR/const-extern-fn-call-extern-fn.rs:9:9 - | -LL | regular_in_block(); - | ^^^^^^^^^^^^^^^^^^ - | - = 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[E0723]: cannot call functions with `"C"` abi in `min_const_fn` - --> $DIR/const-extern-fn-call-extern-fn.rs:18:9 - | -LL | regular(); - | ^^^^^^^^^ - | - = 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: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0723`. diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs deleted file mode 100644 index 5619811768801..0000000000000 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(const_extern_fn)] - -const extern fn unsize(x: &[u8; 3]) -> &[u8] { x } -//~^ ERROR unsizing casts are not allowed in const fn -const unsafe extern "C" fn closure() -> fn() { || {} } -//~^ ERROR function pointers in const fn are unstable -const unsafe extern fn use_float() { 1.0 + 1.0; } -//~^ ERROR only int, `bool` and `char` operations are stable in const fn -const extern "C" fn ptr_cast(val: *const u8) { val as usize; } -//~^ ERROR casting pointers to ints is unstable in const fn - - -fn main() {} diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr deleted file mode 100644 index 0ab1ddd8d5225..0000000000000 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0723]: unsizing casts are not allowed in const fn - --> $DIR/const-extern-fn-min-const-fn.rs:3:48 - | -LL | const extern fn unsize(x: &[u8; 3]) -> &[u8] { x } - | ^ - | - = 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[E0723]: function pointers in const fn are unstable - --> $DIR/const-extern-fn-min-const-fn.rs:5:41 - | -LL | const unsafe extern "C" fn closure() -> fn() { || {} } - | ^^^^ - | - = 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[E0723]: only int, `bool` and `char` operations are stable in const fn - --> $DIR/const-extern-fn-min-const-fn.rs:7:38 - | -LL | const unsafe extern fn use_float() { 1.0 + 1.0; } - | ^^^^^^^^^ - | - = 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[E0723]: casting pointers to ints is unstable in const fn - --> $DIR/const-extern-fn-min-const-fn.rs:9:48 - | -LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; } - | ^^^^^^^^^^^^ - | - = 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: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0723`. diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs deleted file mode 100644 index cab175bbfa818..0000000000000 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(const_extern_fn)] - -const unsafe extern fn foo() -> usize { 5 } - -fn main() { - let a: [u8; foo()]; - //~^ ERROR call to unsafe function is unsafe and requires unsafe function or block - foo(); - //~^ ERROR call to unsafe function is unsafe and requires unsafe function or block -} diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.stderr deleted file mode 100644 index 5196b8ee0a21d..0000000000000 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/const-extern-fn-requires-unsafe.rs:8:5 - | -LL | foo(); - | ^^^^^ call to unsafe function - | - = 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/const-extern-fn-requires-unsafe.rs:6:17 - | -LL | let a: [u8; foo()]; - | ^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn.rs deleted file mode 100644 index 1dc0f83cadf7d..0000000000000 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn.rs +++ /dev/null @@ -1,35 +0,0 @@ -// run-pass -#![feature(const_extern_fn)] - -const extern fn foo1(val: u8) -> u8 { - val + 1 -} - -const extern "C" fn foo2(val: u8) -> u8 { - val + 1 -} - -const unsafe extern fn bar1(val: bool) -> bool { - !val -} - -const unsafe extern "C" fn bar2(val: bool) -> bool { - !val -} - - -fn main() { - let a: [u8; foo1(25) as usize] = [0; 26]; - let b: [u8; foo2(25) as usize] = [0; 26]; - assert_eq!(a, b); - - let bar1_res = unsafe { bar1(false) }; - let bar2_res = unsafe { bar2(false) }; - assert!(bar1_res); - assert_eq!(bar1_res, bar2_res); - - let _foo1_cast: extern fn(u8) -> u8 = foo1; - let _foo2_cast: extern fn(u8) -> u8 = foo2; - let _bar1_cast: unsafe extern fn(bool) -> bool = bar1; - let _bar2_cast: unsafe extern fn(bool) -> bool = bar2; -} diff --git a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs deleted file mode 100644 index d39f2c1fe277e..0000000000000 --- a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Check that `const extern fn` and `const unsafe extern fn` are feature-gated. - -#[cfg(FALSE)] const extern fn foo1() {} //~ ERROR `const extern fn` definitions are unstable -#[cfg(FALSE)] const extern "C" fn foo2() {} //~ ERROR `const extern fn` definitions are unstable -#[cfg(FALSE)] const extern "Rust" fn foo3() {} //~ ERROR `const extern fn` definitions are unstable -#[cfg(FALSE)] const unsafe extern fn bar1() {} //~ ERROR `const extern fn` definitions are unstable -#[cfg(FALSE)] const unsafe extern "C" fn bar2() {} -//~^ ERROR `const extern fn` definitions are unstable -#[cfg(FALSE)] const unsafe extern "Rust" fn bar3() {} -//~^ ERROR `const extern fn` definitions are unstable - -fn main() {} diff --git a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr deleted file mode 100644 index f138620ffefba..0000000000000 --- a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr +++ /dev/null @@ -1,57 +0,0 @@ -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:3:15 - | -LL | #[cfg(FALSE)] const extern fn foo1() {} - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64926 - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:4:15 - | -LL | #[cfg(FALSE)] const extern "C" fn foo2() {} - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64926 - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:5:15 - | -LL | #[cfg(FALSE)] const extern "Rust" fn foo3() {} - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64926 - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:6:15 - | -LL | #[cfg(FALSE)] const unsafe extern fn bar1() {} - | ^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64926 - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:7:15 - | -LL | #[cfg(FALSE)] const unsafe extern "C" fn bar2() {} - | ^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64926 - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:9:15 - | -LL | #[cfg(FALSE)] const unsafe extern "Rust" fn bar3() {} - | ^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64926 - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-external-macro-const-err.rs b/src/test/ui/consts/const-external-macro-const-err.rs deleted file mode 100644 index 616d24f4a7bcf..0000000000000 --- a/src/test/ui/consts/const-external-macro-const-err.rs +++ /dev/null @@ -1,13 +0,0 @@ -// edition:2018 -// aux-build:external_macro.rs - -// Ensure that CONST_ERR lint errors -// are not silenced in external macros. -// https://github.com/rust-lang/rust/issues/65300 - -extern crate external_macro; -use external_macro::static_assert; - -fn main() { - static_assert!(2 + 2 == 5); //~ ERROR -} diff --git a/src/test/ui/consts/const-external-macro-const-err.stderr b/src/test/ui/consts/const-external-macro-const-err.stderr deleted file mode 100644 index 237c4d792c9ea..0000000000000 --- a/src/test/ui/consts/const-external-macro-const-err.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: any use of this value will cause an error - --> $DIR/const-external-macro-const-err.rs:12:5 - | -LL | static_assert!(2 + 2 == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 - | - = note: `#[deny(const_err)]` on by default - = 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/consts/const-int-pow-rpass.rs b/src/test/ui/consts/const-int-pow-rpass.rs deleted file mode 100644 index 8e84a900605f5..0000000000000 --- a/src/test/ui/consts/const-int-pow-rpass.rs +++ /dev/null @@ -1,11 +0,0 @@ -// run-pass - -const IS_POWER_OF_TWO_A: bool = 0u32.is_power_of_two(); -const IS_POWER_OF_TWO_B: bool = 32u32.is_power_of_two(); -const IS_POWER_OF_TWO_C: bool = 33u32.is_power_of_two(); - -fn main() { - assert!(!IS_POWER_OF_TWO_A); - assert!(IS_POWER_OF_TWO_B); - assert!(!IS_POWER_OF_TWO_C); -} diff --git a/src/test/ui/consts/const-int-saturating-arith.rs b/src/test/ui/consts/const-int-saturating-arith.rs index d0a3eccd17763..394d6c17f5adf 100644 --- a/src/test/ui/consts/const-int-saturating-arith.rs +++ b/src/test/ui/consts/const-int-saturating-arith.rs @@ -1,4 +1,5 @@ // run-pass +// ignore-emscripten no i128 support #![feature(const_saturating_int_methods)] const INT_U32_NO: u32 = (42 as u32).saturating_add(2); diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr index 087cc3c86a68d..24d2e3ce53937 100644 --- a/src/test/ui/consts/const-match-check.eval1.stderr +++ b/src/test/ui/consts/const-match-check.eval1.stderr @@ -3,13 +3,6 @@ error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1 | LL | A = { let 0 = 0; 0 }, | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | A = { if let 0 = 0 { /* */ } 0 }, - | ^^^^^^^^^^^^^^^^^^^^^^ 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 80d9f794bc1d5..5d59d06f7982a 100644 --- a/src/test/ui/consts/const-match-check.eval2.stderr +++ b/src/test/ui/consts/const-match-check.eval2.stderr @@ -3,13 +3,6 @@ error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1 | LL | let x: [i32; { let 0 = 0; 0 }] = []; | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | let x: [i32; { if let 0 = 0 { /* */ } 0 }] = []; - | ^^^^^^^^^^^^^^^^^^^^^^ 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 e6b2f212bb430..6d74c26f9f7a5 100644 --- a/src/test/ui/consts/const-match-check.matchck.stderr +++ b/src/test/ui/consts/const-match-check.matchck.stderr @@ -3,52 +3,24 @@ error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1 | LL | const X: i32 = { let 0 = 0; 0 }; | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | const X: i32 = { if let 0 = 0 { /* */ } 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^ 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 }; | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | static Y: i32 = { if let 0 = 0 { /* */ } 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^ 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 }; | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | const X: i32 = { if let 0 = 0 { /* */ } 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^ 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 }; | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | const X: i32 = { if let 0 = 0 { /* */ } 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/const-prop-ice.rs b/src/test/ui/consts/const-prop-ice.rs index 48c4b7da942e4..13309f978b672 100644 --- a/src/test/ui/consts/const-prop-ice.rs +++ b/src/test/ui/consts/const-prop-ice.rs @@ -1,4 +1,3 @@ fn main() { [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3 - //~| ERROR this expression will panic at runtime } diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr index 8ecc6f4bc6b12..4b3880198bf2d 100644 --- a/src/test/ui/consts/const-prop-ice.stderr +++ b/src/test/ui/consts/const-prop-ice.stderr @@ -6,11 +6,5 @@ LL | [0; 3][3u64 as usize]; | = note: `#[deny(const_err)]` on by default -error: this expression will panic at runtime - --> $DIR/const-prop-ice.rs:2:5 - | -LL | [0; 3][3u64 as usize]; - | ^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 3 - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/consts/issue-64506.rs b/src/test/ui/consts/issue-64506.rs deleted file mode 100644 index db3e85a7bdfd1..0000000000000 --- a/src/test/ui/consts/issue-64506.rs +++ /dev/null @@ -1,20 +0,0 @@ -// check-pass - -#[derive(Copy, Clone)] -pub struct ChildStdin { - inner: AnonPipe, -} - -#[derive(Copy, Clone)] -enum AnonPipe {} - -const FOO: () = { - union Foo { - a: ChildStdin, - b: (), - } - let x = unsafe { Foo { b: () }.a }; - let x = &x.inner; -}; - -fn main() {} diff --git a/src/test/ui/consts/issue-64662.rs b/src/test/ui/consts/issue-64662.rs deleted file mode 100644 index e3a8c85830f73..0000000000000 --- a/src/test/ui/consts/issue-64662.rs +++ /dev/null @@ -1,10 +0,0 @@ -enum Foo { - A = foo(), //~ ERROR: type annotations needed - B = foo(), //~ ERROR: type annotations needed -} - -const fn foo() -> isize { - 0 -} - -fn main() {} diff --git a/src/test/ui/consts/issue-64662.stderr b/src/test/ui/consts/issue-64662.stderr deleted file mode 100644 index b81daae330bfa..0000000000000 --- a/src/test/ui/consts/issue-64662.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0282]: type annotations needed - --> $DIR/issue-64662.rs:2:9 - | -LL | A = foo(), - | ^^^ cannot infer type for `T` - -error[E0282]: type annotations needed - --> $DIR/issue-64662.rs:3:9 - | -LL | B = foo(), - | ^^^ cannot infer type for `T` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/consts/issue-65348.rs b/src/test/ui/consts/issue-65348.rs deleted file mode 100644 index 5eafa831d6317..0000000000000 --- a/src/test/ui/consts/issue-65348.rs +++ /dev/null @@ -1,23 +0,0 @@ -// check-pass - -struct Generic(T); - -impl Generic { - const ARRAY: [T; 0] = []; - const NEWTYPE_ARRAY: Generic<[T; 0]> = Generic([]); - const ARRAY_FIELD: Generic<(i32, [T; 0])> = Generic((0, [])); -} - -pub const fn array() -> &'static T { - &Generic::::ARRAY[0] -} - -pub const fn newtype_array() -> &'static T { - &Generic::::NEWTYPE_ARRAY.0[0] -} - -pub const fn array_field() -> &'static T { - &(Generic::::ARRAY_FIELD.0).1[0] -} - -fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index 3158b6284db94..7919cfe987cfc 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -324,5 +324,5 @@ LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } error: aborting due to 37 previous errors -Some errors have detailed explanations: E0493, E0515, E0723. -For more information about an error, try `rustc --explain E0493`. +Some errors have detailed explanations: E0515, E0723. +For more information about an error, try `rustc --explain E0515`. 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 37016664ac58f..5bc7b70638c80 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 @@ -6,4 +6,3 @@ LL | const F: u32 = (U::X, 42).1; error: aborting due to previous error -For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.rs b/src/test/ui/consts/miri_unleashed/non_const_fn.rs deleted file mode 100644 index e1ac4306575da..0000000000000 --- a/src/test/ui/consts/miri_unleashed/non_const_fn.rs +++ /dev/null @@ -1,13 +0,0 @@ -// compile-flags: -Zunleash-the-miri-inside-of-you -#![warn(const_err)] - -// A test demonstrating that we prevent calling non-const fn during CTFE. - -fn foo() {} - -const C: () = foo(); //~ WARN: skipping const checks -//~^ WARN any use of this value will cause an error - -fn main() { - println!("{:?}", C); //~ ERROR: evaluation of constant expression failed -} diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr deleted file mode 100644 index 7a574b34304cb..0000000000000 --- a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr +++ /dev/null @@ -1,29 +0,0 @@ -warning: skipping const checks - --> $DIR/non_const_fn.rs:8:15 - | -LL | const C: () = foo(); - | ^^^^^ - -warning: any use of this value will cause an error - --> $DIR/non_const_fn.rs:8:15 - | -LL | const C: () = foo(); - | --------------^^^^^- - | | - | calling non-const function `foo` - | -note: lint level defined here - --> $DIR/non_const_fn.rs:2:9 - | -LL | #![warn(const_err)] - | ^^^^^^^^^ - -error[E0080]: evaluation of constant expression failed - --> $DIR/non_const_fn.rs:12:22 - | -LL | println!("{:?}", C); - | ^ referenced constant has errors - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/promote_const_let.polonius.stderr b/src/test/ui/consts/promote_const_let.polonius.stderr new file mode 100644 index 0000000000000..cf41bd7bdb1eb --- /dev/null +++ b/src/test/ui/consts/promote_const_let.polonius.stderr @@ -0,0 +1,29 @@ +error[E0597]: `y` does not live long enough + --> $DIR/promote_const_let.rs:4:9 + | +LL | let x: &'static u32 = { + | - borrow later stored here +LL | let y = 42; +LL | &y + | ^^ borrowed value does not live long enough +LL | }; + | - `y` dropped here while still borrowed + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote_const_let.rs:6:28 + | +LL | let x: &'static u32 = &{ + | ____________------------____^ + | | | + | | type annotation requires that borrow lasts for `'static` +LL | | let y = 42; +LL | | y +LL | | }; + | |_____^ creates a temporary which is freed while still in use +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0597, E0716. +For more information about an error, try `rustc --explain E0597`. diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index 2fb9977f4d700..0733a51233e33 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -16,30 +16,26 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim | LL | pub struct Foo(A, B); | --------------------------- required by `Foo` -LL | -LL | impl Foo { - | - help: consider restricting this bound: `A: std::marker::Sized` ... 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 | -LL | impl Foo { - | - help: consider restricting this bound: `B: std::marker::Sized` ... 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 diff --git a/src/test/ui/conversion-methods.stderr b/src/test/ui/conversion-methods.stderr index 5c666afb89a33..b9662e7607494 100644 --- a/src/test/ui/conversion-methods.stderr +++ b/src/test/ui/conversion-methods.stderr @@ -41,7 +41,7 @@ LL | let _prove_piercing_earnest: Vec = &[1, 2, 3]; | ^^^^^^^^^^ | | | expected struct `std::vec::Vec`, found reference - | help: try using a conversion method: `(&[1, 2, 3]).to_vec()` + | help: try using a conversion method: `&[1, 2, 3].to_vec()` | = note: expected type `std::vec::Vec` found type `&[{integer}; 3]` diff --git a/src/test/ui/debuginfo-lto.rs b/src/test/ui/debuginfo-lto.rs index 43f75b0344be7..e4beee9e737ba 100644 --- a/src/test/ui/debuginfo-lto.rs +++ b/src/test/ui/debuginfo-lto.rs @@ -7,7 +7,6 @@ // aux-build:debuginfo-lto-aux.rs // compile-flags: -C lto -g // no-prefer-dynamic -// ignore-asmjs wasm2js does not support source maps yet extern crate debuginfo_lto_aux; diff --git a/src/test/ui/never_type/defaulted-never-note.rs b/src/test/ui/defaulted-never-note.rs similarity index 100% rename from src/test/ui/never_type/defaulted-never-note.rs rename to src/test/ui/defaulted-never-note.rs diff --git a/src/test/ui/never_type/defaulted-never-note.stderr b/src/test/ui/defaulted-never-note.stderr similarity index 100% rename from src/test/ui/never_type/defaulted-never-note.stderr rename to src/test/ui/defaulted-never-note.stderr diff --git a/src/test/ui/deprecation/deprecation-sanity.stderr b/src/test/ui/deprecation/deprecation-sanity.stderr index 57143d6810554..7ff68a1038b1c 100644 --- a/src/test/ui/deprecation/deprecation-sanity.stderr +++ b/src/test/ui/deprecation/deprecation-sanity.stderr @@ -54,5 +54,5 @@ LL | #[deprecated(since = "a", since = "b", note = "c")] error: aborting due to 9 previous errors -Some errors have detailed explanations: E0538, E0541, E0550, E0551, E0565. +Some errors have detailed explanations: E0538, E0541, E0565. For more information about an error, try `rustc --explain E0538`. diff --git a/src/test/ui/deprecation/derive_on_deprecated.rs b/src/test/ui/deprecation/derive_on_deprecated.rs index ac771ac81d118..ed4055ecdd38c 100644 --- a/src/test/ui/deprecation/derive_on_deprecated.rs +++ b/src/test/ui/deprecation/derive_on_deprecated.rs @@ -6,10 +6,4 @@ #[derive(Default)] struct X; -#[deprecated(note="Do not use this")] -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)] -pub struct Step { - _skip: Option, -} - fn main() {} diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs index 1893355205433..6902779f33d23 100644 --- a/src/test/ui/did_you_mean/issue-40396.rs +++ b/src/test/ui/did_you_mean/issue-40396.rs @@ -1,8 +1,16 @@ -fn main() { +fn foo() { (0..13).collect>(); //~^ ERROR chained comparison +} + +fn bar() { Vec::new(); //~^ ERROR chained comparison +} + +fn qux() { (0..13).collect(); //~^ ERROR chained comparison } + +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 7fc7c2628c472..7a08fda27e355 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -2,31 +2,28 @@ error: chained comparison operators require parentheses --> $DIR/issue-40396.rs:2:20 | LL | (0..13).collect>(); - | ^^^^^ -help: use `::<...>` instead of `<...>` to specify type arguments + | ^^^^^^^^ | -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:4:8 + --> $DIR/issue-40396.rs:7:8 | LL | Vec::new(); - | ^^^^^ -help: use `::<...>` instead of `<...>` to specify type arguments + | ^^^^^^^ | -LL | Vec::::new(); - | ^^ + = 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:6:20 + --> $DIR/issue-40396.rs:12:20 | LL | (0..13).collect(); - | ^^^^^ -help: use `::<...>` instead of `<...>` to specify type arguments + | ^^^^^^^^ | -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: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr index 79bc7d2565be6..84235ca4d6372 100644 --- a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr +++ b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr @@ -2,7 +2,7 @@ error: `~` cannot be used as a unary operator --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:2:13 | LL | let x = ~1; - | ^ help: use `!` to perform bitwise not + | ^ help: use `!` to perform bitwise negation error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr index ef68bf52cf3bd..d02f30152d687 100644 --- a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr +++ b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr @@ -5,10 +5,10 @@ LL | let x = Option(1); | ^^^^^^ help: try using one of the enum's variants | -LL | let x = std::option::Option::None(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | let x = std::option::Option::Some(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = std::prelude::v1::Option::None(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = std::prelude::v1::Option::Some(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0532]: expected tuple struct/variant, found enum `Option` --> $DIR/issue-43871-enum-instead-of-variant.rs:21:12 @@ -17,10 +17,10 @@ LL | if let Option(_) = x { | ^^^^^^ help: try using one of the enum's variants | -LL | if let std::option::Option::None(_) = x { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | if let std::option::Option::Some(_) = x { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | if let std::prelude::v1::Option::None(_) = x { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | if let std::prelude::v1::Option::Some(_) = x { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0532]: expected tuple struct/variant, found enum `Example` --> $DIR/issue-43871-enum-instead-of-variant.rs:27:12 @@ -47,15 +47,15 @@ LL | let z = ManyVariants(); | ^^^^^^^^^^^^ help: try using one of the enum's variants | -LL | let z = ManyVariants::One(); - | ^^^^^^^^^^^^^^^^^ -LL | let z = ManyVariants::Two(); - | ^^^^^^^^^^^^^^^^^ -LL | let z = ManyVariants::Three(); +LL | let z = ManyVariants::Eight(); | ^^^^^^^^^^^^^^^^^^^ +LL | let z = ManyVariants::Five(); + | ^^^^^^^^^^^^^^^^^^ LL | let z = ManyVariants::Four(); | ^^^^^^^^^^^^^^^^^^ - and 6 other candidates +LL | let z = ManyVariants::Nine(); + | ^^^^^^^^^^^^^^^^^^ +and 6 other candidates error: aborting due to 5 previous errors diff --git a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr index cb350a1faeed2..8d3a86df0233d 100644 --- a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr +++ b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr @@ -13,7 +13,7 @@ LL | fn setup() -> Determine { Set } | ^^^^^^^^^ LL | fn setup() -> PutDown { Set } | ^^^^^^^ - and 3 other candidates +and 3 other candidates error[E0425]: cannot find value `Set` in this scope --> $DIR/issue-56028-there-is-an-enum-variant.rs:9:21 @@ -30,7 +30,7 @@ LL | use Determine::Set; | LL | use PutDown::Set; | - and 3 other candidates +and 3 other candidates error: aborting due to 2 previous errors diff --git a/src/test/ui/never_type/dispatch_from_dyn_zst.rs b/src/test/ui/dispatch_from_dyn_zst.rs similarity index 100% rename from src/test/ui/never_type/dispatch_from_dyn_zst.rs rename to src/test/ui/dispatch_from_dyn_zst.rs diff --git a/src/test/ui/never_type/diverging-fallback-control-flow.rs b/src/test/ui/diverging-fallback-control-flow.rs similarity index 99% rename from src/test/ui/never_type/diverging-fallback-control-flow.rs rename to src/test/ui/diverging-fallback-control-flow.rs index c68e6364ed406..0f0f787b407d2 100644 --- a/src/test/ui/never_type/diverging-fallback-control-flow.rs +++ b/src/test/ui/diverging-fallback-control-flow.rs @@ -4,7 +4,6 @@ #![allow(unused_assignments)] #![allow(unused_variables)] #![allow(unreachable_code)] - // Test various cases where we permit an unconstrained variable // to fallback based on control-flow. // diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs index bec86d6465ae9..91063edf0f6c4 100644 --- a/src/test/ui/drop/dynamic-drop-async.rs +++ b/src/test/ui/drop/dynamic-drop-async.rs @@ -5,7 +5,7 @@ // run-pass // edition:2018 -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![feature(slice_patterns)] #![allow(unused)] diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index 5a7568fe2cd50..8516bc3d96424 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -2,13 +2,12 @@ #![allow(unused_assignments)] #![allow(unused_variables)] -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait, untagged_unions)] #![feature(slice_patterns)] use std::cell::{Cell, RefCell}; -use std::mem::ManuallyDrop; use std::ops::Generator; use std::panic; use std::pin::Pin; @@ -153,16 +152,17 @@ fn assignment1(a: &Allocator, c0: bool) { _v = _w; } +#[allow(unions_with_drop_fields)] union Boxy { - a: ManuallyDrop, - b: ManuallyDrop, + a: T, + b: T, } fn union1(a: &Allocator) { unsafe { - let mut u = Boxy { a: ManuallyDrop::new(a.alloc()) }; - *u.b = a.alloc(); // drops first alloc - drop(ManuallyDrop::into_inner(u.a)); + let mut u = Boxy { a: a.alloc() }; + u.b = a.alloc(); + drop(u.a); } } diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr b/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr new file mode 100644 index 0000000000000..5e93a0234259c --- /dev/null +++ b/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr @@ -0,0 +1,78 @@ +error[E0597]: `o2` does not live long enough + --> $DIR/dropck_trait_cycle_checked.rs:111:13 + | +LL | o1.set0(&o2); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `o2` dropped here while still borrowed + | 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 + | +LL | o1.set1(&o3); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `o3` dropped here while still borrowed + | 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 + | +LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); + | -------- cast requires that `o2` is borrowed for `'static` +... +LL | o2.set0(&o2); + | ^^^ borrowed value does not live long enough +... +LL | } + | - `o2` dropped here while still borrowed + +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` +... +LL | o2.set1(&o3); + | ^^^ borrowed value does not live long enough +... +LL | } + | - `o3` dropped here while still borrowed + +error[E0597]: `o1` does not live long enough + --> $DIR/dropck_trait_cycle_checked.rs:115:13 + | +LL | o3.set0(&o1); + | ^^^ borrowed value does not live long enough +LL | o3.set1(&o2); +LL | } + | - + | | + | `o1` dropped here while still borrowed + | borrow might be used here, when `o1` is dropped and runs the destructor for type `std::boxed::Box>` + +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` +... +LL | o3.set1(&o2); + | ^^^ borrowed value does not live long enough +LL | } + | - `o2` dropped here while still borrowed + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/dst/dst-object-from-unsized-type.stderr b/src/test/ui/dst/dst-object-from-unsized-type.stderr index 40db575eabd38..55ac625fc985b 100644 --- a/src/test/ui/dst/dst-object-from-unsized-type.stderr +++ b/src/test/ui/dst/dst-object-from-unsized-type.stderr @@ -1,25 +1,23 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/dst-object-from-unsized-type.rs:8:23 | -LL | fn test1(t: &T) { - | -- help: consider further restricting this bound: `T: std::marker::Sized +` LL | let u: &dyn Foo = t; | ^ 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 for the cast to the object type `dyn Foo` error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/dst-object-from-unsized-type.rs:13:23 | -LL | fn test2(t: &T) { - | -- help: consider further restricting this bound: `T: std::marker::Sized +` LL | let v: &dyn Foo = t as &dyn Foo; | ^ 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 for the cast to the object type `dyn Foo` error[E0277]: the size for values of type `str` cannot be known at compilation time diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr index d865b59f0b945..7d59d553d88fd 100644 --- a/src/test/ui/empty/empty-never-array.stderr +++ b/src/test/ui/empty/empty-never-array.stderr @@ -11,13 +11,6 @@ LL | | } ... LL | let Helper::U(u) = Helper::T(t, []); | ^^^^^^^^^^^^ pattern `T(_, _)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let Helper::U(u) = Helper::T(t, []) { /* */ } - | error[E0381]: use of possibly-uninitialized variable: `u` --> $DIR/empty-never-array.rs:12:5 diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr index 9712157552716..b9681db87b67e 100644 --- a/src/test/ui/empty/empty-struct-braces-expr.stderr +++ b/src/test/ui/empty/empty-struct-braces-expr.stderr @@ -1,9 +1,6 @@ error[E0423]: expected value, found struct `Empty1` --> $DIR/empty-struct-braces-expr.rs:15:14 | -LL | struct Empty1 {} - | ---------------- `Empty1` defined here -... LL | let e1 = Empty1; | ^^^^^^ | | @@ -13,9 +10,6 @@ LL | let e1 = Empty1; error[E0423]: expected function, found struct `Empty1` --> $DIR/empty-struct-braces-expr.rs:16:14 | -LL | struct Empty1 {} - | ---------------- `Empty1` defined here -... LL | let e1 = Empty1(); | ^^^^^^ | | @@ -25,18 +19,12 @@ LL | let e1 = Empty1(); error[E0423]: expected value, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-expr.rs:17:14 | -LL | Empty3 {} - | --------- `E::Empty3` defined here -... LL | let e3 = E::Empty3; | ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`? error[E0423]: expected function, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-expr.rs:18:14 | -LL | Empty3 {} - | --------- `E::Empty3` defined here -... LL | let e3 = E::Empty3(); | ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`? diff --git a/src/test/ui/empty/empty-struct-braces-pat-1.stderr b/src/test/ui/empty/empty-struct-braces-pat-1.stderr index 271e811a2fd65..6c361c703440c 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-1.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-1.stderr @@ -1,9 +1,6 @@ error[E0532]: expected unit struct/variant or constant, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-pat-1.rs:24:9 | -LL | Empty3 {} - | --------- `E::Empty3` defined here -... LL | E::Empty3 => () | ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`? diff --git a/src/test/ui/empty/empty-struct-braces-pat-2.stderr b/src/test/ui/empty/empty-struct-braces-pat-2.stderr index 3352473788894..12047b5880c3e 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-2.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-2.stderr @@ -1,9 +1,6 @@ error[E0532]: expected tuple struct/variant, found struct `Empty1` --> $DIR/empty-struct-braces-pat-2.rs:15:9 | -LL | struct Empty1 {} - | ---------------- `Empty1` defined here -... LL | Empty1() => () | ^^^^^^ | | @@ -22,9 +19,6 @@ LL | XEmpty1() => () error[E0532]: expected tuple struct/variant, found struct `Empty1` --> $DIR/empty-struct-braces-pat-2.rs:21:9 | -LL | struct Empty1 {} - | ---------------- `Empty1` defined here -... LL | Empty1(..) => () | ^^^^^^ | | diff --git a/src/test/ui/empty/empty-struct-braces-pat-3.stderr b/src/test/ui/empty/empty-struct-braces-pat-3.stderr index aefdd772b1bfd..af8731b5f0596 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-3.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-3.stderr @@ -1,9 +1,6 @@ error[E0532]: expected tuple struct/variant, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-pat-3.rs:17:9 | -LL | Empty3 {} - | --------- `E::Empty3` defined here -... LL | E::Empty3() => () | ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`? @@ -19,9 +16,6 @@ LL | XE::XEmpty3() => () error[E0532]: expected tuple struct/variant, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-pat-3.rs:25:9 | -LL | Empty3 {} - | --------- `E::Empty3` defined here -... LL | E::Empty3(..) => () | ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`? diff --git a/src/test/ui/empty/empty-struct-tuple-pat.stderr b/src/test/ui/empty/empty-struct-tuple-pat.stderr index 4b828c0d942e3..6c15e7bf282ce 100644 --- a/src/test/ui/empty/empty-struct-tuple-pat.stderr +++ b/src/test/ui/empty/empty-struct-tuple-pat.stderr @@ -19,11 +19,8 @@ LL | XEmpty6 => () error[E0532]: expected unit struct/variant or constant, found tuple variant `E::Empty4` --> $DIR/empty-struct-tuple-pat.rs:29:9 | -LL | Empty4() - | -------- `E::Empty4` defined here -... LL | E::Empty4 => () - | ^^^^^^^^^ did you mean `E::Empty4( /* fields */ )`? + | ^^^^^^^^^ 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 @@ -32,7 +29,7 @@ LL | XE::XEmpty5 => (), | ^^^^------- | | | | | help: a unit variant with a similar name exists: `XEmpty4` - | did you mean `XE::XEmpty5( /* fields */ )`? + | did you mean `XE::XEmpty5 ( /* fields */ )`? error: aborting due to 4 previous errors diff --git a/src/test/ui/enum/enum-variant-type-2.stderr b/src/test/ui/enum/enum-variant-type-2.stderr index 7e8453c61f62b..65c45d9bad0dc 100644 --- a/src/test/ui/enum/enum-variant-type-2.stderr +++ b/src/test/ui/enum/enum-variant-type-2.stderr @@ -9,4 +9,3 @@ LL | fn foo(x: Foo::Bar) {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr index 577c6e886d523..56a4bcffc81a2 100644 --- a/src/test/ui/error-codes/E0005.stderr +++ b/src/test/ui/error-codes/E0005.stderr @@ -3,13 +3,6 @@ error[E0005]: refutable pattern in local binding: `None` not covered | LL | let Some(y) = x; | ^^^^^^^ pattern `None` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let Some(y) = x { /* */ } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0392.stderr b/src/test/ui/error-codes/E0392.stderr index 7b0bfe372757a..d0b808df184c4 100644 --- a/src/test/ui/error-codes/E0392.stderr +++ b/src/test/ui/error-codes/E0392.stderr @@ -4,7 +4,7 @@ error[E0392]: parameter `T` is never used LL | enum Foo { Bar } | ^ unused parameter | - = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `T` or using a marker such as `std::marker::PhantomData` error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr index 754006bc217ee..ec240003f9182 100644 --- a/src/test/ui/error-codes/E0423.stderr +++ b/src/test/ui/error-codes/E0423.stderr @@ -27,14 +27,11 @@ LL | for _ in (std::ops::Range { start: 0, end: 10 }) {} error[E0423]: expected function, found struct `Foo` --> $DIR/E0423.rs:4:13 | -LL | struct Foo { a: bool }; - | ---------------------- `Foo` defined here -LL | LL | let f = Foo(); | ^^^ | | | did you mean `Foo { /* fields */ }`? - | help: a function with a similar name exists (notice the capitalization): `foo` + | help: a function with a similar name exists: `foo` error[E0423]: expected value, found struct `T` --> $DIR/E0423.rs:14:8 diff --git a/src/test/ui/error-codes/E0424.stderr b/src/test/ui/error-codes/E0424.stderr index 567d1b3cc75f4..d67a2660dac38 100644 --- a/src/test/ui/error-codes/E0424.stderr +++ b/src/test/ui/error-codes/E0424.stderr @@ -1,20 +1,14 @@ error[E0424]: expected value, found module `self` --> $DIR/E0424.rs:7:9 | -LL | / fn foo() { -LL | | self.bar(); - | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter -LL | | } - | |_____- this function doesn't have a `self` parameter +LL | self.bar(); + | ^^^^ `self` value is a keyword only available in methods with `self` parameter error[E0424]: expected unit struct/variant or constant, found module `self` --> $DIR/E0424.rs:12:9 | -LL | / fn main () { -LL | | let self = "self"; - | | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed -LL | | } - | |_- this function doesn't have a `self` parameter +LL | let self = "self"; + | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0478.stderr b/src/test/ui/error-codes/E0478.stderr index 1380840e0db2d..587125fdc336e 100644 --- a/src/test/ui/error-codes/E0478.stderr +++ b/src/test/ui/error-codes/E0478.stderr @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied LL | child: Box + 'SnowWhite>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'SnowWhite` as defined on the struct at 3:22 +note: lifetime parameter instantiated with the lifetime 'SnowWhite as defined on the struct at 3:22 --> $DIR/E0478.rs:3:22 | LL | struct Prince<'kiss, 'SnowWhite> { | ^^^^^^^^^^ -note: but lifetime parameter must outlive the lifetime `'kiss` as defined on the struct at 3:15 +note: but lifetime parameter must outlive the lifetime 'kiss as defined on the struct at 3:15 --> $DIR/E0478.rs:3:15 | LL | struct Prince<'kiss, 'SnowWhite> { diff --git a/src/test/ui/error-codes/E0617.rs b/src/test/ui/error-codes/E0617.rs index c832e09ac1118..439c3db576864 100644 --- a/src/test/ui/error-codes/E0617.rs +++ b/src/test/ui/error-codes/E0617.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + extern { fn printf(c: *const i8, ...); } @@ -20,7 +22,7 @@ fn main() { //~^ ERROR can't pass `u16` to variadic function //~| HELP cast the value to `c_uint` printf(::std::ptr::null(), printf); - //~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function - //~| HELP cast the value to `unsafe extern "C" fn(*const i8, ...)` + //~^ ERROR can't pass `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaListImpl<'r>, ...) {printf}` to variadic function + //~| HELP cast the value to `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaListImpl<'r>, ...)` } } diff --git a/src/test/ui/error-codes/E0617.stderr b/src/test/ui/error-codes/E0617.stderr index 7c4df099d0dd1..d866320bbcdf7 100644 --- a/src/test/ui/error-codes/E0617.stderr +++ b/src/test/ui/error-codes/E0617.stderr @@ -1,42 +1,42 @@ error[E0617]: can't pass `f32` to variadic function - --> $DIR/E0617.rs:7:36 + --> $DIR/E0617.rs:9:36 | LL | printf(::std::ptr::null(), 0f32); | ^^^^ help: cast the value to `c_double`: `0f32 as c_double` error[E0617]: can't pass `i8` to variadic function - --> $DIR/E0617.rs:10:36 + --> $DIR/E0617.rs:12:36 | LL | printf(::std::ptr::null(), 0i8); | ^^^ help: cast the value to `c_int`: `0i8 as c_int` error[E0617]: can't pass `i16` to variadic function - --> $DIR/E0617.rs:13:36 + --> $DIR/E0617.rs:15:36 | LL | printf(::std::ptr::null(), 0i16); | ^^^^ help: cast the value to `c_int`: `0i16 as c_int` error[E0617]: can't pass `u8` to variadic function - --> $DIR/E0617.rs:16:36 + --> $DIR/E0617.rs:18:36 | LL | printf(::std::ptr::null(), 0u8); | ^^^ help: cast the value to `c_uint`: `0u8 as c_uint` error[E0617]: can't pass `u16` to variadic function - --> $DIR/E0617.rs:19:36 + --> $DIR/E0617.rs:21:36 | LL | printf(::std::ptr::null(), 0u16); | ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint` -error[E0617]: can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function - --> $DIR/E0617.rs:22:36 +error[E0617]: can't pass `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaListImpl<'r>, ...) {printf}` to variadic function + --> $DIR/E0617.rs:24:36 | LL | printf(::std::ptr::null(), printf); | ^^^^^^ -help: cast the value to `unsafe extern "C" fn(*const i8, ...)` +help: cast the value to `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaListImpl<'r>, ...)` | -LL | printf(::std::ptr::null(), printf as unsafe extern "C" fn(*const i8, ...)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | printf(::std::ptr::null(), printf as for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaListImpl<'r>, ...)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr index feca7f10b706b..f50c64780118b 100644 --- a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr +++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr @@ -27,4 +27,3 @@ LL | invoke(&x, |a, b| if a > b { a } else { b }); error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/exhaustive_integer_patterns.rs b/src/test/ui/exhaustive_integer_patterns.rs index 59f749198971b..2570bc8a56078 100644 --- a/src/test/ui/exhaustive_integer_patterns.rs +++ b/src/test/ui/exhaustive_integer_patterns.rs @@ -1,7 +1,7 @@ #![feature(precise_pointer_size_matching)] #![feature(exclusive_range_pattern)] + #![deny(unreachable_patterns)] -#![deny(overlapping_patterns)] use std::{char, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128}; @@ -41,8 +41,7 @@ fn main() { match x { //~ ERROR non-exhaustive patterns -7 => {} -5..=120 => {} - -2..=20 => {} - //~^ ERROR unreachable pattern + -2..=20 => {} //~ ERROR unreachable pattern 125 => {} } @@ -136,9 +135,9 @@ fn main() { (125 .. 128, false) => {} } - match 0u8 { + match 0u8 { // ok 0 .. 2 => {} - 1 ..= 2 => {} //~ ERROR multiple patterns covering the same range + 1 ..= 2 => {} _ => {} } diff --git a/src/test/ui/exhaustive_integer_patterns.stderr b/src/test/ui/exhaustive_integer_patterns.stderr index 7a3a36a820c65..6c4b7b0cc0352 100644 --- a/src/test/ui/exhaustive_integer_patterns.stderr +++ b/src/test/ui/exhaustive_integer_patterns.stderr @@ -5,7 +5,7 @@ LL | 200 => {} | ^^^ | note: lint level defined here - --> $DIR/exhaustive_integer_patterns.rs:3:9 + --> $DIR/exhaustive_integer_patterns.rs:4:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | match x { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `std::i8::MIN` not covered - --> $DIR/exhaustive_integer_patterns.rs:83:11 + --> $DIR/exhaustive_integer_patterns.rs:82:11 | LL | match 0i8 { | ^^^ pattern `std::i8::MIN` not covered @@ -49,7 +49,7 @@ LL | match 0i8 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `0i16` not covered - --> $DIR/exhaustive_integer_patterns.rs:91:11 + --> $DIR/exhaustive_integer_patterns.rs:90:11 | LL | match 0i16 { | ^^^^ pattern `0i16` not covered @@ -57,7 +57,7 @@ LL | match 0i16 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `128u8..=std::u8::MAX` not covered - --> $DIR/exhaustive_integer_patterns.rs:109:11 + --> $DIR/exhaustive_integer_patterns.rs:108:11 | LL | match 0u8 { | ^^^ pattern `128u8..=std::u8::MAX` not covered @@ -65,7 +65,7 @@ LL | match 0u8 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=std::u8::MAX, Some(_))` not covered - --> $DIR/exhaustive_integer_patterns.rs:121:11 + --> $DIR/exhaustive_integer_patterns.rs:120:11 | LL | match (0u8, Some(())) { | ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=std::u8::MAX, Some(_))` not covered @@ -73,29 +73,15 @@ LL | match (0u8, Some(())) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `(126u8..=127u8, false)` not covered - --> $DIR/exhaustive_integer_patterns.rs:126:11 + --> $DIR/exhaustive_integer_patterns.rs:125:11 | LL | match (0u8, true) { | ^^^^^^^^^^^ pattern `(126u8..=127u8, false)` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: multiple patterns covering the same range - --> $DIR/exhaustive_integer_patterns.rs:141:9 - | -LL | 0 .. 2 => {} - | ------ this range overlaps on `1u8` -LL | 1 ..= 2 => {} - | ^^^^^^^ overlapping patterns - | -note: lint level defined here - --> $DIR/exhaustive_integer_patterns.rs:4:9 - | -LL | #![deny(overlapping_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered - --> $DIR/exhaustive_integer_patterns.rs:146:11 + --> $DIR/exhaustive_integer_patterns.rs:145:11 | LL | match 0u128 { | ^^^^^ pattern `std::u128::MAX` not covered @@ -103,7 +89,7 @@ LL | match 0u128 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `5u128..=std::u128::MAX` not covered - --> $DIR/exhaustive_integer_patterns.rs:150:11 + --> $DIR/exhaustive_integer_patterns.rs:149:11 | LL | match 0u128 { | ^^^^^ pattern `5u128..=std::u128::MAX` not covered @@ -111,13 +97,13 @@ LL | match 0u128 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `0u128..=3u128` not covered - --> $DIR/exhaustive_integer_patterns.rs:154:11 + --> $DIR/exhaustive_integer_patterns.rs:153:11 | LL | match 0u128 { | ^^^^^ pattern `0u128..=3u128` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to 14 previous errors +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr index cbd6422e5df76..4bf2d573d4f96 100644 --- a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr +++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr @@ -6,12 +6,12 @@ LL | Foo<'b,'a> | = note: expected type `Foo<'a, 'b>` found type `Foo<'b, 'a>` -note: the lifetime `'b` as defined on the impl at 6:9... +note: the lifetime 'b as defined on the impl at 6:9... --> $DIR/explicit-self-lifetime-mismatch.rs:6:9 | LL | impl<'a,'b> Foo<'a,'b> { | ^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 6:6 +note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 6:6 --> $DIR/explicit-self-lifetime-mismatch.rs:6:6 | LL | impl<'a,'b> Foo<'a,'b> { @@ -25,12 +25,12 @@ LL | Foo<'b,'a> | = note: expected type `Foo<'a, 'b>` found type `Foo<'b, 'a>` -note: the lifetime `'a` as defined on the impl at 6:6... +note: the lifetime 'a as defined on the impl at 6:6... --> $DIR/explicit-self-lifetime-mismatch.rs:6:6 | LL | impl<'a,'b> Foo<'a,'b> { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 6:9 +note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 6:9 --> $DIR/explicit-self-lifetime-mismatch.rs:6:9 | LL | impl<'a,'b> Foo<'a,'b> { diff --git a/src/test/ui/expr_attr_paren_order.stderr b/src/test/ui/expr_attr_paren_order.stderr index 57a9350c089a8..89f615f53ddd3 100644 --- a/src/test/ui/expr_attr_paren_order.stderr +++ b/src/test/ui/expr_attr_paren_order.stderr @@ -2,7 +2,7 @@ error: variable `X` should have a snake case name --> $DIR/expr_attr_paren_order.rs:19:17 | LL | let X = 0; - | ^ help: convert the identifier to snake case (notice the capitalization): `x` + | ^ help: convert the identifier to snake case: `x` | note: lint level defined here --> $DIR/expr_attr_paren_order.rs:17:17 diff --git a/src/test/ui/extern/extern-const.fixed b/src/test/ui/extern/extern-const.fixed index 9d96b4f63fb6c..0eec9fb3ee647 100644 --- a/src/test/ui/extern/extern-const.fixed +++ b/src/test/ui/extern/extern-const.fixed @@ -5,8 +5,7 @@ // compile. To sidestep this by using one that *is* defined. // run-rustfix -// ignore-wasm32-bare no external library to link to. -// ignore-asmjs wasm2js does not support source maps yet +// ignore-wasm32 no external library to link to. // compile-flags: -g #![feature(rustc_private)] extern crate libc; diff --git a/src/test/ui/extern/extern-const.rs b/src/test/ui/extern/extern-const.rs index 7cef5b3497b5a..ca5d7ddf27e3a 100644 --- a/src/test/ui/extern/extern-const.rs +++ b/src/test/ui/extern/extern-const.rs @@ -5,8 +5,7 @@ // compile. To sidestep this by using one that *is* defined. // run-rustfix -// ignore-wasm32-bare no external library to link to. -// ignore-asmjs wasm2js does not support source maps yet +// ignore-wasm32 no external library to link to. // compile-flags: -g #![feature(rustc_private)] extern crate libc; diff --git a/src/test/ui/extern/extern-const.stderr b/src/test/ui/extern/extern-const.stderr index 258202b6903d3..77406be2095cf 100644 --- a/src/test/ui/extern/extern-const.stderr +++ b/src/test/ui/extern/extern-const.stderr @@ -1,5 +1,5 @@ error: extern items cannot be `const` - --> $DIR/extern-const.rs:16:5 + --> $DIR/extern-const.rs:15:5 | LL | const rust_dbg_static_mut: libc::c_int; | ^^^^^ help: try using a static value: `static` 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 deleted file mode 100644 index ff10d412a110a..0000000000000 --- a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs +++ /dev/null @@ -1,65 +0,0 @@ -// 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 deleted file mode 100644 index bc15fcb0e3996..0000000000000 --- a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +++ /dev/null @@ -1,83 +0,0 @@ -// 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/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs index 8c567ece1875b..68ff95e420895 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 @@ -32,13 +32,9 @@ // check-pass -#![feature(test, plugin_registrar)] +#![feature(test)] #![warn(unused_attributes, unknown_lints)] -// Exception, a gated and deprecated attribute. - -#![plugin_registrar] //~ WARN unused attribute - // UNGATED WHITE-LISTED BUILT-IN ATTRIBUTES #![warn(x5400)] //~ WARN unknown lint: `x5400` @@ -47,6 +43,7 @@ #![deny(x5100)] //~ WARN unknown lint: `x5100` #![macro_use] // (allowed if no argument; see issue-43160-gating-of-macro_use.rs) #![macro_export] //~ WARN unused attribute +#![plugin_registrar] //~ WARN unused attribute // skipping testing of cfg // skipping testing of cfg_attr #![main] //~ WARN unused attribute 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 e78d9840abf7d..b2a6018b5354d 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 @@ -1,5 +1,5 @@ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:9 | LL | #![warn(x5400)] | ^^^^^ @@ -11,233 +11,197 @@ LL | #![warn(unused_attributes, unknown_lints)] | ^^^^^^^^^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:10 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:41:10 | LL | #![allow(x5300)] | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:11 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:42:11 | LL | #![forbid(x5200)] | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:47:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:43:9 | LL | #![deny(x5100)] | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:104:8 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:101:8 | LL | #[warn(x5400)] | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:107:25 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:104:25 | LL | mod inner { #![warn(x5400)] } | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:110:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:107:12 | LL | #[warn(x5400)] fn f() { } | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:113:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:110:12 | LL | #[warn(x5400)] struct S; | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:116:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:113:12 | LL | #[warn(x5400)] type T = S; | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:119:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:116:12 | LL | #[warn(x5400)] impl S { } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:123:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:120:9 | LL | #[allow(x5300)] | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:126:26 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:123:26 | LL | mod inner { #![allow(x5300)] } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:129:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:126:13 | LL | #[allow(x5300)] fn f() { } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:132:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:129:13 | LL | #[allow(x5300)] struct S; | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:135:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:132:13 | LL | #[allow(x5300)] type T = S; | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:138:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:135:13 | LL | #[allow(x5300)] impl S { } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:142:10 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:139:10 | LL | #[forbid(x5200)] | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:145:27 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:142:27 | LL | mod inner { #![forbid(x5200)] } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:148:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:145:14 | LL | #[forbid(x5200)] fn f() { } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:151:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:148:14 | LL | #[forbid(x5200)] struct S; | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:154:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:151:14 | LL | #[forbid(x5200)] type T = S; | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:157:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:154:14 | LL | #[forbid(x5200)] impl S { } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:161:8 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:158:8 | LL | #[deny(x5100)] | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:164:25 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:161:25 | LL | mod inner { #![deny(x5100)] } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:167:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:164:12 | LL | #[deny(x5100)] fn f() { } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:170:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:167:12 | LL | #[deny(x5100)] struct S; | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:173:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:170:12 | LL | #[deny(x5100)] type T = S; | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:176:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:173:12 | LL | #[deny(x5100)] impl S { } | ^^^^^ warning: macro_escape is a deprecated synonym for macro_use - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:460:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:457:1 | LL | #[macro_escape] | ^^^^^^^^^^^^^^^ warning: macro_escape is a deprecated synonym for macro_use - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:463:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:460:17 | LL | mod inner { #![macro_escape] } | ^^^^^^^^^^^^^^^^ | = help: consider an outer attribute, `#[macro_use]` mod ... -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:17 - | -LL | mod inner { #![plugin_registrar] } - | ^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - | - = note: `#[warn(deprecated)]` on by default - -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:224:5 - | -LL | #[plugin_registrar] struct S; - | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:5 - | -LL | #[plugin_registrar] type T = S; - | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:230:5 - | -LL | #[plugin_registrar] impl S { } - | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:1 - | -LL | #[plugin_registrar] - | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:1 - | -LL | #![plugin_registrar] - | ^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - warning: use of deprecated attribute `crate_id`: no longer used. - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:90:1 + --> $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:95:1 + --> $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:93:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:90:12 | LL | #![feature(rust1)] | ^^^^^ @@ -245,7 +209,7 @@ LL | #![feature(rust1)] = note: `#[warn(stable_features)]` on by default warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:184:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:181:5 | LL | #[macro_use] fn f() { } | ^^^^^^^^^^^^ @@ -257,979 +221,979 @@ LL | #![warn(unused_attributes, unknown_lints)] | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:187:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:184:5 | LL | #[macro_use] struct S; | ^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:187:5 | LL | #[macro_use] type T = S; | ^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:193:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:5 | LL | #[macro_use] impl S { } | ^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:200:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:197:17 | LL | mod inner { #![macro_export] } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:203:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:200:5 | LL | #[macro_export] fn f() { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:206:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:203:5 | LL | #[macro_export] struct S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:209:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:206:5 | LL | #[macro_export] type T = S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:212:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:209:5 | LL | #[macro_export] impl S { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:197:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:194:1 | LL | #[macro_export] | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:17 | LL | mod inner { #![plugin_registrar] } | ^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:224:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:221:5 | LL | #[plugin_registrar] struct S; | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:224:5 | LL | #[plugin_registrar] type T = S; | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:230:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:5 | LL | #[plugin_registrar] impl S { } | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:1 | LL | #[plugin_registrar] | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:237:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:234:17 | LL | mod inner { #![main] } | ^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:242:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:239:5 | LL | #[main] struct S; | ^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:242:5 | LL | #[main] type T = S; | ^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:248:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:5 | LL | #[main] impl S { } | ^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:234:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:231:1 | LL | #[main] | ^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:255:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:252:17 | LL | mod inner { #![start] } | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:260:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:257:5 | LL | #[start] struct S; | ^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:260:5 | LL | #[start] type T = S; | ^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:5 | LL | #[start] impl S { } | ^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:252:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:249:1 | LL | #[start] | ^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:319:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:316:5 | LL | #[path = "3800"] fn f() { } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:322:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:319:5 | LL | #[path = "3800"] struct S; | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:325:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:322:5 | LL | #[path = "3800"] type T = S; | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:328:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:325:5 | LL | #[path = "3800"] impl S { } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:332:17 | LL | mod inner { #![automatically_derived] } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:338:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:5 | LL | #[automatically_derived] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:338:5 | LL | #[automatically_derived] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5 | LL | #[automatically_derived] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:347:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5 | LL | #[automatically_derived] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:332:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:329:1 | LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:17 | LL | mod inner { #![no_link] } | ^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:5 | LL | #[no_link] fn f() { } | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:373:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5 | LL | #[no_link] struct S; | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:373:5 | LL | #[no_link]type T = S; | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:379:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:5 | LL | #[no_link] impl S { } | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:1 | LL | #[no_link] | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:17 | LL | mod inner { #![should_panic] } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:5 | LL | #[should_panic] fn f() { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:5 | LL | #[should_panic] struct S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:5 | LL | #[should_panic] type T = S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:5 | LL | #[should_panic] impl S { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:1 | LL | #[should_panic] | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:405:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:402:17 | LL | mod inner { #![ignore] } | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:405:5 | LL | #[ignore] fn f() { } | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:411:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:5 | LL | #[ignore] struct S; | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:411:5 | LL | #[ignore] type T = S; | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:5 | LL | #[ignore] impl S { } | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:402:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:1 | LL | #[ignore] | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:424:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:421:17 | LL | mod inner { #![no_implicit_prelude] } | ^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:427:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:424:5 | LL | #[no_implicit_prelude] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:430:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:427:5 | LL | #[no_implicit_prelude] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:433:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:430:5 | LL | #[no_implicit_prelude] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:433:5 | LL | #[no_implicit_prelude] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:421:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:1 | LL | #[no_implicit_prelude] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:443:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:440:17 | LL | mod inner { #![reexport_test_harness_main="2900"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:446:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:443:5 | LL | #[reexport_test_harness_main = "2900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:449:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:446:5 | LL | #[reexport_test_harness_main = "2900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:452:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:449:5 | LL | #[reexport_test_harness_main = "2900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:452:5 | LL | #[reexport_test_harness_main = "2900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:440:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:437:1 | LL | #[reexport_test_harness_main = "2900"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:463:5 | LL | #[macro_escape] fn f() { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:469:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5 | LL | #[macro_escape] struct S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:472:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:469:5 | LL | #[macro_escape] type T = S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:475:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:472:5 | LL | #[macro_escape] impl S { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:17 | LL | mod inner { #![no_std] } | ^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:17 | LL | mod inner { #![no_std] } | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:484:5 | LL | #[no_std] fn f() { } | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:484:5 | LL | #[no_std] fn f() { } | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:491:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5 | LL | #[no_std] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:491:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5 | LL | #[no_std] struct S; | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:495:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:492:5 | LL | #[no_std] type T = S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:495:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:492:5 | LL | #[no_std] type T = S; | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:5 | LL | #[no_std] impl S { } | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:5 | LL | #[no_std] impl S { } | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:1 | LL | #[no_std] | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:1 | LL | #[no_std] | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:638:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:635:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:638:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:635:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:642:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:642:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:643:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:643:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:650:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:650:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:654:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:654:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:634:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:631:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:634:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:631:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:664:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:664:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:656:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:656:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:689:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:689:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:681:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:681:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:714:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17 | LL | mod inner { #![no_main] } | ^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:714:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17 | LL | mod inner { #![no_main] } | ^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5 | LL | #[no_main] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5 | LL | #[no_main] fn f() { } | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:722:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5 | LL | #[no_main] struct S; | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:722:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5 | LL | #[no_main] struct S; | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5 | LL | #[no_main] type T = S; | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5 | LL | #[no_main] type T = S; | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:730:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5 | LL | #[no_main] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:730:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5 | LL | #[no_main] impl S { } | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:710:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1 | LL | #[no_main] | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:710:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1 | LL | #[no_main] | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:774:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:774:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:781:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:778:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:781:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:778:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:1 | -LL | #![plugin_registrar] - | ^^^^^^^^^^^^^^^^^^^^ +LL | #![macro_export] + | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:1 | -LL | #![macro_export] - | ^^^^^^^^^^^^^^^^ +LL | #![plugin_registrar] + | ^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:52:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:1 | LL | #![main] | ^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:50:1 | LL | #![start] | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:56:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1 | LL | #![repr()] | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:58:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:55:1 | LL | #![path = "3800"] | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:56:1 | LL | #![automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:61:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:58:1 | LL | #![no_link] | ^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:63:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1 | LL | #![should_panic] | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:61:1 | LL | #![ignore] | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:67:1 | LL | #![proc_macro_derive()] | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/bench.rs b/src/test/ui/feature-gates/bench.rs index 8de390becbe7d..afe4dc7d54c9b 100644 --- a/src/test/ui/feature-gates/bench.rs +++ b/src/test/ui/feature-gates/bench.rs @@ -1,9 +1,5 @@ -// edition:2018 - #[bench] //~ ERROR use of unstable library feature 'test' //~| WARN this was previously accepted fn bench() {} -use bench as _; //~ ERROR use of unstable library feature 'test' - //~| WARN this was previously accepted fn main() {} diff --git a/src/test/ui/feature-gates/bench.stderr b/src/test/ui/feature-gates/bench.stderr index 168ac92572437..b9e24e931d42b 100644 --- a/src/test/ui/feature-gates/bench.stderr +++ b/src/test/ui/feature-gates/bench.stderr @@ -1,5 +1,5 @@ error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable - --> $DIR/bench.rs:3:3 + --> $DIR/bench.rs:1:3 | LL | #[bench] | ^^^^^ @@ -8,14 +8,5 @@ LL | #[bench] = 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 #64266 -error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable - --> $DIR/bench.rs:7:5 - | -LL | use bench as _; - | ^^^^^ - | - = 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 #64266 - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs index 00737d8428b3d..3d75251e15616 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -1,7 +1,7 @@ #![feature(untagged_unions)] -trait Tr1 { type As1: Copy; } -trait Tr2 { type As2: Copy; } +trait Tr1 { type As1; } +trait Tr2 { type As2; } struct S1; #[derive(Copy, Clone)] @@ -32,7 +32,7 @@ enum _En1> { union _Un1> { //~^ ERROR associated type bounds are unstable - outest: std::mem::ManuallyDrop, + outest: T, outer: T::As1, inner: ::As2, } @@ -70,7 +70,3 @@ fn main() { // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // let _: &dyn Tr1 = &S1; } - -macro_rules! accept_path { ($p:path) => {} } -accept_path!(Iterator); -//~^ ERROR associated type bounds are unstable diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr index a7ab7614d7b78..84af2a0163ae4 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -115,15 +115,6 @@ LL | let _: impl Tr1 = S1; = note: for more information, see https://github.com/rust-lang/rust/issues/52662 = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable -error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:75:23 - | -LL | accept_path!(Iterator); - | ^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/52662 - = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable - error[E0562]: `impl Trait` not allowed outside of function and inherent method return types --> $DIR/feature-gate-associated_type_bounds.rs:54:14 | @@ -148,7 +139,7 @@ LL | let _: impl Tr1 = S1; | = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable -error: aborting due to 17 previous errors +error: aborting due to 16 previous errors Some errors have detailed explanations: E0562, E0658. For more information about an error, try `rustc --explain E0562`. diff --git a/src/test/ui/feature-gates/feature-gate-box_patterns.rs b/src/test/ui/feature-gates/feature-gate-box_patterns.rs index c5b926d5af28c..8bec16a974e80 100644 --- a/src/test/ui/feature-gates/feature-gate-box_patterns.rs +++ b/src/test/ui/feature-gates/feature-gate-box_patterns.rs @@ -2,6 +2,3 @@ fn main() { let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental println!("x: {}", x); } - -macro_rules! accept_pat { ($p:pat) => {} } -accept_pat!(box 0); //~ ERROR box pattern syntax is experimental diff --git a/src/test/ui/feature-gates/feature-gate-box_patterns.stderr b/src/test/ui/feature-gates/feature-gate-box_patterns.stderr index 1e47bd41e8870..d2dafe93a862f 100644 --- a/src/test/ui/feature-gates/feature-gate-box_patterns.stderr +++ b/src/test/ui/feature-gates/feature-gate-box_patterns.stderr @@ -7,15 +7,6 @@ LL | let box x = Box::new('c'); = note: for more information, see https://github.com/rust-lang/rust/issues/29641 = help: add `#![feature(box_patterns)]` to the crate attributes to enable -error[E0658]: box pattern syntax is experimental - --> $DIR/feature-gate-box_patterns.rs:7:13 - | -LL | accept_pat!(box 0); - | ^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29641 - = help: add `#![feature(box_patterns)]` 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 E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-box_syntax.rs b/src/test/ui/feature-gates/feature-gate-box_syntax.rs index c23953a9e099e..778660cc0b549 100644 --- a/src/test/ui/feature-gates/feature-gate-box_syntax.rs +++ b/src/test/ui/feature-gates/feature-gate-box_syntax.rs @@ -1,9 +1,6 @@ // Test that the use of the box syntax is gated by `box_syntax` feature gate. -#[cfg(FALSE)] -fn foo() { +fn main() { let x = box 3; //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead } - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-box_syntax.stderr b/src/test/ui/feature-gates/feature-gate-box_syntax.stderr index cbafa50257706..61b0534d2dc3e 100644 --- a/src/test/ui/feature-gates/feature-gate-box_syntax.stderr +++ b/src/test/ui/feature-gates/feature-gate-box_syntax.stderr @@ -1,5 +1,5 @@ error[E0658]: box expression syntax is experimental; you can call `Box::new` instead - --> $DIR/feature-gate-box_syntax.rs:5:13 + --> $DIR/feature-gate-box_syntax.rs:4:13 | LL | let x = box 3; | ^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs deleted file mode 100644 index 1ab11ce3b4423..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs +++ /dev/null @@ -1,9 +0,0 @@ -struct ConstFn; -//~^ ERROR const generics are unstable -//~^^ ERROR using function pointers as const generic parameters is unstable - -struct ConstPtr; -//~^ ERROR const generics are unstable -//~^^ ERROR using raw pointers as const generic parameters is unstable - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr deleted file mode 100644 index 790bc33e2683e..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0658]: const generics are unstable - --> $DIR/feature-gate-const_generics-ptr.rs:1:16 - | -LL | struct ConstFn; - | ^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/44580 - = help: add `#![feature(const_generics)]` to the crate attributes to enable - -error[E0658]: const generics are unstable - --> $DIR/feature-gate-const_generics-ptr.rs:5:17 - | -LL | struct ConstPtr; - | ^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/44580 - = help: add `#![feature(const_generics)]` to the crate attributes to enable - -error[E0658]: using function pointers as const generic parameters is unstable - --> $DIR/feature-gate-const_generics-ptr.rs:1:25 - | -LL | struct ConstFn; - | ^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/53020 - = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable - -error[E0658]: using raw pointers as const generic parameters is unstable - --> $DIR/feature-gate-const_generics-ptr.rs:5:26 - | -LL | struct ConstPtr; - | ^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/53020 - = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable - -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-const_generics.rs b/src/test/ui/feature-gates/feature-gate-const_generics.rs index 0adc9902a6937..fe1ded1c4bbc4 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics.rs +++ b/src/test/ui/feature-gates/feature-gate-const_generics.rs @@ -2,9 +2,4 @@ fn foo() {} //~ ERROR const generics are unstable struct Foo([(); X]); //~ ERROR const generics are unstable -macro_rules! accept_item { ($i:item) => {} } -accept_item! { - impl A {} //~ ERROR const generics are unstable -} - fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.stderr b/src/test/ui/feature-gates/feature-gate-const_generics.stderr index f0154ed289f14..468e9c31d37e2 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_generics.stderr @@ -1,30 +1,21 @@ error[E0658]: const generics are unstable - --> $DIR/feature-gate-const_generics.rs:1:8 + --> $DIR/feature-gate-const_generics.rs:1:14 | LL | fn foo() {} - | ^^^^^^^^^^^ + | ^ | = note: for more information, see https://github.com/rust-lang/rust/issues/44580 = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: const generics are unstable - --> $DIR/feature-gate-const_generics.rs:3:12 + --> $DIR/feature-gate-const_generics.rs:3:18 | LL | struct Foo([(); X]); - | ^^^^^^^^^^^^^^ + | ^ | = note: for more information, see https://github.com/rust-lang/rust/issues/44580 = help: add `#![feature(const_generics)]` to the crate attributes to enable -error[E0658]: const generics are unstable - --> $DIR/feature-gate-const_generics.rs:7:10 - | -LL | impl A {} - | ^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/44580 - = help: add `#![feature(const_generics)]` to the crate attributes to enable - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.rs b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.rs index 7517fb280ea78..0e3f6b168be6b 100644 --- a/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.rs +++ b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.rs @@ -5,7 +5,4 @@ crate struct Bender { //~ ERROR `crate` visibility modifier is experimental water: bool, } -macro_rules! accept_vis { ($v:vis) => {} } -accept_vis!(crate); //~ ERROR `crate` visibility modifier is experimental - fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr index b317872cea817..1e061eced3660 100644 --- a/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr +++ b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr @@ -7,15 +7,6 @@ LL | crate struct Bender { = note: for more information, see https://github.com/rust-lang/rust/issues/53120 = help: add `#![feature(crate_visibility_modifier)]` to the crate attributes to enable -error[E0658]: `crate` visibility modifier is experimental - --> $DIR/feature-gate-crate_visibility_modifier.rs:9:13 - | -LL | accept_vis!(crate); - | ^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/53120 - = help: add `#![feature(crate_visibility_modifier)]` 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 E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-decl_macro.rs b/src/test/ui/feature-gates/feature-gate-decl_macro.rs index b208a047481a4..d002c5dbbd2db 100644 --- a/src/test/ui/feature-gates/feature-gate-decl_macro.rs +++ b/src/test/ui/feature-gates/feature-gate-decl_macro.rs @@ -2,8 +2,4 @@ macro m() {} //~ ERROR `macro` is experimental -macro_rules! accept_item { ($i:item) => {} } -accept_item! { - macro m() {} //~ ERROR `macro` is experimental -} fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-decl_macro.stderr b/src/test/ui/feature-gates/feature-gate-decl_macro.stderr index c6690ebd4d917..905a1b1531044 100644 --- a/src/test/ui/feature-gates/feature-gate-decl_macro.stderr +++ b/src/test/ui/feature-gates/feature-gate-decl_macro.stderr @@ -7,15 +7,6 @@ LL | macro m() {} = note: for more information, see https://github.com/rust-lang/rust/issues/39412 = help: add `#![feature(decl_macro)]` to the crate attributes to enable -error[E0658]: `macro` is experimental - --> $DIR/feature-gate-decl_macro.rs:7:5 - | -LL | macro m() {} - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/39412 - = help: add `#![feature(decl_macro)]` 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 E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.rs b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.rs index 594ec73fe26f7..ded08b93fe81c 100644 --- a/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.rs +++ b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.rs @@ -1,10 +1,6 @@ -#[cfg(FALSE)] -fn foo() { +pub fn main() { match 22 { 0 .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental - PATH .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental _ => {} } } - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr index 075fdbed90d6c..ee20408d1781f 100644 --- a/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr +++ b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr @@ -1,21 +1,12 @@ error[E0658]: exclusive range pattern syntax is experimental - --> $DIR/feature-gate-exclusive-range-pattern.rs:4:11 + --> $DIR/feature-gate-exclusive-range-pattern.rs:3:9 | LL | 0 .. 3 => {} - | ^^ + | ^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/37854 = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable -error[E0658]: exclusive range pattern syntax is experimental - --> $DIR/feature-gate-exclusive-range-pattern.rs:5:14 - | -LL | PATH .. 3 => {} - | ^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/37854 - = help: add `#![feature(exclusive_range_pattern)]` 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 E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs index f0cc9ea70550e..27ff5ace25ddc 100644 --- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs +++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs @@ -1,5 +1,4 @@ #![feature(never_type)] - fn foo() -> Result { Ok(123) } diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr index 08c36cece4cf9..dd4ca1f67e330 100644 --- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr +++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr @@ -1,15 +1,8 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered - --> $DIR/feature-gate-exhaustive-patterns.rs:8:9 + --> $DIR/feature-gate-exhaustive-patterns.rs:7:9 | LL | let Ok(_x) = foo(); | ^^^^^^ pattern `Err(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let Ok(_x) = foo() { /* */ } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-label_break_value.rs b/src/test/ui/feature-gates/feature-gate-label_break_value.rs index 8d7ecd27b450f..6fc38f45517ef 100644 --- a/src/test/ui/feature-gates/feature-gate-label_break_value.rs +++ b/src/test/ui/feature-gates/feature-gate-label_break_value.rs @@ -1,8 +1,5 @@ -#[cfg(FALSE)] -pub fn foo() { +pub fn main() { 'a: { //~ ERROR labels on blocks are unstable break 'a; } } - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-label_break_value.stderr b/src/test/ui/feature-gates/feature-gate-label_break_value.stderr index 6a861d3e04f92..a417e0eec22f2 100644 --- a/src/test/ui/feature-gates/feature-gate-label_break_value.stderr +++ b/src/test/ui/feature-gates/feature-gate-label_break_value.stderr @@ -1,5 +1,5 @@ error[E0658]: labels on blocks are unstable - --> $DIR/feature-gate-label_break_value.rs:3:5 + --> $DIR/feature-gate-label_break_value.rs:2:5 | LL | 'a: { | ^^ diff --git a/src/test/ui/feature-gates/feature-gate-macros_in_extern.rs b/src/test/ui/feature-gates/feature-gate-macros_in_extern.rs new file mode 100644 index 0000000000000..125af64fef05c --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-macros_in_extern.rs @@ -0,0 +1,27 @@ +#![feature(decl_macro)] + +macro_rules! returns_isize( + ($ident:ident) => ( + fn $ident() -> isize; + ) +); + +macro takes_u32_returns_u32($ident:ident) { + fn $ident (arg: u32) -> u32; +} + +macro_rules! emits_nothing( + () => () +); + +#[link(name = "rust_test_helpers", kind = "static")] +extern { + returns_isize!(rust_get_test_int); + //~^ ERROR macro invocations in `extern {}` blocks are experimental + takes_u32_returns_u32!(rust_dbg_extern_identity_u32); + //~^ ERROR macro invocations in `extern {}` blocks are experimental + emits_nothing!(); + //~^ ERROR macro invocations in `extern {}` blocks are experimental +} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-macros_in_extern.stderr b/src/test/ui/feature-gates/feature-gate-macros_in_extern.stderr new file mode 100644 index 0000000000000..e8b3ab5dda20d --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-macros_in_extern.stderr @@ -0,0 +1,30 @@ +error[E0658]: macro invocations in `extern {}` blocks are experimental + --> $DIR/feature-gate-macros_in_extern.rs:19:5 + | +LL | returns_isize!(rust_get_test_int); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49476 + = help: add `#![feature(macros_in_extern)]` to the crate attributes to enable + +error[E0658]: macro invocations in `extern {}` blocks are experimental + --> $DIR/feature-gate-macros_in_extern.rs:21:5 + | +LL | takes_u32_returns_u32!(rust_dbg_extern_identity_u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49476 + = help: add `#![feature(macros_in_extern)]` to the crate attributes to enable + +error[E0658]: macro invocations in `extern {}` blocks are experimental + --> $DIR/feature-gate-macros_in_extern.rs:23:5 + | +LL | emits_nothing!(); + | ^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49476 + = help: add `#![feature(macros_in_extern)]` 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/feature-gates/feature-gate-non_exhaustive.rs b/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs new file mode 100644 index 0000000000000..950f170f4fd41 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs @@ -0,0 +1,10 @@ +//#![feature(non_exhaustive)] + +#[non_exhaustive] //~ERROR the `#[non_exhaustive]` attribute is an experimental feature +pub enum NonExhaustiveEnum { + Unit, + Tuple(u32), + Struct { field: u32 } +} + +fn main() { } diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr b/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr new file mode 100644 index 0000000000000..482332b8d706c --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[non_exhaustive]` attribute is an experimental feature + --> $DIR/feature-gate-non_exhaustive.rs:3:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/44109 + = help: add `#![feature(non_exhaustive)]` 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/feature-gates/feature-gate-object_safe_for_dispatch.rs b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs deleted file mode 100644 index 8945360b7be6d..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Test that the use of the non object-safe trait objects -// are gated by `object_safe_for_dispatch` feature gate. - -trait NonObjectSafe1: Sized {} - -trait NonObjectSafe2 { - fn static_fn() {} -} - -trait NonObjectSafe3 { - fn foo(&self); -} - -trait NonObjectSafe4 { - fn foo(&self, &Self); -} - -fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { - //~^ ERROR E0038 -} - -fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { - //~^ ERROR E0038 - loop {} -} - -fn takes_non_object_safe_box(obj: Box) { - //~^ ERROR E0038 -} - -fn return_non_object_safe_rc() -> std::rc::Rc { - //~^ ERROR E0038 - loop {} -} - -trait Trait {} - -impl Trait for dyn NonObjectSafe1 {} -//~^ ERROR E0038 - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr deleted file mode 100644 index 54e64e2fc1bd4..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:1 - | -LL | fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe1` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - -error[E0038]: the trait `NonObjectSafe2` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:22:1 - | -LL | fn static_fn() {} - | --------- associated function `static_fn` has no `self` parameter -... -LL | fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe2` cannot be made into an object - -error[E0038]: the trait `NonObjectSafe3` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:1 - | -LL | fn foo(&self); - | --- method `foo` has generic type parameters -... -LL | fn takes_non_object_safe_box(obj: Box) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe3` cannot be made into an object - -error[E0038]: the trait `NonObjectSafe4` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:31:1 - | -LL | fn foo(&self, &Self); - | --- method `foo` references the `Self` type in its parameters or return type -... -LL | fn return_non_object_safe_rc() -> std::rc::Rc { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe4` cannot be made into an object - -error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:6 - | -LL | impl Trait for dyn NonObjectSafe1 {} - | ^^^^^ the trait `NonObjectSafe1` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/feature-gates/feature-gate-plugin.rs b/src/test/ui/feature-gates/feature-gate-plugin.rs index 8904ec0448ada..977a5556899ba 100644 --- a/src/test/ui/feature-gates/feature-gate-plugin.rs +++ b/src/test/ui/feature-gates/feature-gate-plugin.rs @@ -1,7 +1,6 @@ // Test that `#![plugin(...)]` attribute is gated by `plugin` feature gate #![plugin(foo)] -//~^ ERROR compiler plugins are deprecated -//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated +//~^ ERROR compiler plugins are experimental and possibly buggy fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-plugin.stderr b/src/test/ui/feature-gates/feature-gate-plugin.stderr index f89ddf995c49e..0da9653c9af73 100644 --- a/src/test/ui/feature-gates/feature-gate-plugin.stderr +++ b/src/test/ui/feature-gates/feature-gate-plugin.stderr @@ -1,4 +1,4 @@ -error[E0658]: compiler plugins are deprecated +error[E0658]: compiler plugins are experimental and possibly buggy --> $DIR/feature-gate-plugin.rs:3:1 | LL | #![plugin(foo)] @@ -7,14 +7,6 @@ LL | #![plugin(foo)] = note: for more information, see https://github.com/rust-lang/rust/issues/29597 = help: add `#![feature(plugin)]` to the crate attributes to enable -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/feature-gate-plugin.rs:3:1 - | -LL | #![plugin(foo)] - | ^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - | - = note: `#[warn(deprecated)]` on by default - error: aborting due to previous error For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-plugin_registrar.rs b/src/test/ui/feature-gates/feature-gate-plugin_registrar.rs index 80e4aa76b4771..0e357f89d14a6 100644 --- a/src/test/ui/feature-gates/feature-gate-plugin_registrar.rs +++ b/src/test/ui/feature-gates/feature-gate-plugin_registrar.rs @@ -3,9 +3,6 @@ // the registration function isn't typechecked yet #[plugin_registrar] -//~^ ERROR compiler plugins are deprecated -//~| WARN use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated pub fn registrar() {} -//~^ ERROR compiler plugins are experimental and possibly buggy - +//~^ ERROR compiler plugins are experimental fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr b/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr index 4856cf7c3f7d9..93473bfd27b45 100644 --- a/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr +++ b/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr @@ -1,5 +1,5 @@ error[E0658]: compiler plugins are experimental and possibly buggy - --> $DIR/feature-gate-plugin_registrar.rs:8:1 + --> $DIR/feature-gate-plugin_registrar.rs:6:1 | LL | pub fn registrar() {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -7,23 +7,6 @@ LL | pub fn registrar() {} = note: for more information, see https://github.com/rust-lang/rust/issues/29597 = help: add `#![feature(plugin_registrar)]` to the crate attributes to enable -error[E0658]: compiler plugins are deprecated - --> $DIR/feature-gate-plugin_registrar.rs:5:1 - | -LL | #[plugin_registrar] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29597 - = help: add `#![feature(plugin_registrar)]` to the crate attributes to enable - -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/feature-gate-plugin_registrar.rs:5:1 - | -LL | #[plugin_registrar] - | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - | - = note: `#[warn(deprecated)]` on by default - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr index 02c8400e03e82..dfaa85bc5f014 100644 --- a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr +++ b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr @@ -26,5 +26,4 @@ LL | #[repr(simd)] error: aborting due to 2 previous errors -Some errors have detailed explanations: E0566, E0658. -For more information about an error, try `rustc --explain E0566`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.rs b/src/test/ui/feature-gates/feature-gate-track_caller.rs deleted file mode 100644 index 5865cf0a4f754..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-track_caller.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[track_caller] -fn f() {} -//~^^ ERROR the `#[track_caller]` attribute is an experimental feature - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.stderr b/src/test/ui/feature-gates/feature-gate-track_caller.stderr deleted file mode 100644 index b890019ee4f3c..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-track_caller.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: the `#[track_caller]` attribute is an experimental feature - --> $DIR/feature-gate-track_caller.rs:1:1 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/47809 - = help: add `#![feature(track_caller)]` 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/feature-gates/feature-gate-trait-alias.rs b/src/test/ui/feature-gates/feature-gate-trait-alias.rs index 4b94d7d6d3bda..819085adddade 100644 --- a/src/test/ui/feature-gates/feature-gate-trait-alias.rs +++ b/src/test/ui/feature-gates/feature-gate-trait-alias.rs @@ -1,13 +1,4 @@ trait Foo = Default; //~^ ERROR trait aliases are experimental -macro_rules! accept_item { - ($i:item) => {} -} - -accept_item! { - trait Foo = Ord + Eq; - //~^ ERROR trait aliases are experimental -} - fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-trait-alias.stderr b/src/test/ui/feature-gates/feature-gate-trait-alias.stderr index b1bf6ad349129..9250e27d15807 100644 --- a/src/test/ui/feature-gates/feature-gate-trait-alias.stderr +++ b/src/test/ui/feature-gates/feature-gate-trait-alias.stderr @@ -7,15 +7,6 @@ LL | trait Foo = Default; = note: for more information, see https://github.com/rust-lang/rust/issues/41517 = help: add `#![feature(trait_alias)]` to the crate attributes to enable -error[E0658]: trait aliases are experimental - --> $DIR/feature-gate-trait-alias.rs:9:5 - | -LL | trait Foo = Ord + Eq; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/41517 - = help: add `#![feature(trait_alias)]` 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 E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-try_blocks.rs b/src/test/ui/feature-gates/feature-gate-try_blocks.rs index b451ba84a1565..06cadd82c0731 100644 --- a/src/test/ui/feature-gates/feature-gate-try_blocks.rs +++ b/src/test/ui/feature-gates/feature-gate-try_blocks.rs @@ -1,12 +1,9 @@ // compile-flags: --edition 2018 -#[cfg(FALSE)] -fn foo() { - let try_result: Option<_> = try { //~ ERROR `try` blocks are unstable +pub fn main() { + let try_result: Option<_> = try { //~ ERROR `try` expression is experimental let x = 5; x }; assert_eq!(try_result, Some(5)); } - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-try_blocks.stderr b/src/test/ui/feature-gates/feature-gate-try_blocks.stderr index 44a7d9b9043fd..565f3610a2e21 100644 --- a/src/test/ui/feature-gates/feature-gate-try_blocks.stderr +++ b/src/test/ui/feature-gates/feature-gate-try_blocks.stderr @@ -1,5 +1,5 @@ -error[E0658]: `try` blocks are unstable - --> $DIR/feature-gate-try_blocks.rs:5:33 +error[E0658]: `try` expression is experimental + --> $DIR/feature-gate-try_blocks.rs:4:33 | LL | let try_result: Option<_> = try { | _________________________________^ 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 655891d802c1c..7a597157300ed 100644 --- a/src/test/ui/feature-gates/feature-gate-type_ascription.rs +++ b/src/test/ui/feature-gates/feature-gate-type_ascription.rs @@ -1,8 +1,5 @@ // Type ascription is unstable -#[cfg(FALSE)] -fn foo() { +fn main() { let a = 10: u8; //~ ERROR type ascription is experimental } - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-type_ascription.stderr b/src/test/ui/feature-gates/feature-gate-type_ascription.stderr index d63d624c6c112..83f95529f0d9d 100644 --- a/src/test/ui/feature-gates/feature-gate-type_ascription.stderr +++ b/src/test/ui/feature-gates/feature-gate-type_ascription.stderr @@ -1,5 +1,5 @@ error[E0658]: type ascription is experimental - --> $DIR/feature-gate-type_ascription.rs:5:13 + --> $DIR/feature-gate-type_ascription.rs:4:13 | LL | let a = 10: u8; | ^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.rs b/src/test/ui/feature-gates/feature-gate-untagged_unions.rs index 9ee0e6f681dcc..3bac3d853e907 100644 --- a/src/test/ui/feature-gates/feature-gate-untagged_unions.rs +++ b/src/test/ui/feature-gates/feature-gate-untagged_unions.rs @@ -7,11 +7,11 @@ union U2 { // OK } union U3 { //~ ERROR unions with non-`Copy` fields are unstable - a: String, //~ ERROR unions may not contain fields that need dropping + a: String, } union U4 { //~ ERROR unions with non-`Copy` fields are unstable - a: T, //~ ERROR unions may not contain fields that need dropping + a: T, } union U5 { //~ ERROR unions with `Drop` implementations are unstable diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr index 2182b3a313efb..f59a34e2c81f6 100644 --- a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr +++ b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr @@ -6,7 +6,7 @@ LL | | a: String, LL | | } | |_^ | - = note: for more information, see https://github.com/rust-lang/rust/issues/55149 + = note: for more information, see https://github.com/rust-lang/rust/issues/32836 = help: add `#![feature(untagged_unions)]` to the crate attributes to enable error[E0658]: unions with non-`Copy` fields are unstable @@ -17,7 +17,7 @@ LL | | a: T, LL | | } | |_^ | - = note: for more information, see https://github.com/rust-lang/rust/issues/55149 + = note: for more information, see https://github.com/rust-lang/rust/issues/32836 = help: add `#![feature(untagged_unions)]` to the crate attributes to enable error[E0658]: unions with `Drop` implementations are unstable @@ -28,34 +28,9 @@ LL | | a: u8, LL | | } | |_^ | - = note: for more information, see https://github.com/rust-lang/rust/issues/55149 + = note: for more information, see https://github.com/rust-lang/rust/issues/32836 = help: add `#![feature(untagged_unions)]` to the crate attributes to enable -error[E0740]: unions may not contain fields that need dropping - --> $DIR/feature-gate-untagged_unions.rs:10:5 - | -LL | a: String, - | ^^^^^^^^^ - | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/feature-gate-untagged_unions.rs:10:5 - | -LL | a: String, - | ^^^^^^^^^ - -error[E0740]: unions may not contain fields that need dropping - --> $DIR/feature-gate-untagged_unions.rs:14:5 - | -LL | a: T, - | ^^^^ - | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/feature-gate-untagged_unions.rs:14:5 - | -LL | a: T, - | ^^^^ - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0658, E0740. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0658`. 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 759fb170f90dd..6d8ac7e8f2911 100644 --- a/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs +++ b/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs @@ -1,4 +1,3 @@ -// ignore-emscripten compiled with panic=abort by default // compile-flags: -C no-prepopulate-passes -Cpasses=name-anon-globals #![crate_type = "lib"] 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 97365c34d0148..10cc494213507 100644 --- a/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr +++ b/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr @@ -1,5 +1,5 @@ error[E0658]: the `#[unwind]` attribute is an experimental feature - --> $DIR/feature-gate-unwind-attributes.rs:12:5 + --> $DIR/feature-gate-unwind-attributes.rs:11:5 | LL | #[unwind(allowed)] | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/fmt/format-string-error.rs b/src/test/ui/fmt/format-string-error.rs index 691c06a2402c5..cca949aab6364 100644 --- a/src/test/ui/fmt/format-string-error.rs +++ b/src/test/ui/fmt/format-string-error.rs @@ -48,6 +48,4 @@ fn main() { "###); //~^^^ ERROR invalid format string: unmatched `}` found - println!("{} {} {}", 1, 2); - //~^ ERROR 3 positional arguments in format string, but there are 2 arguments } diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr index 32119b18774b2..3dc122a7399dd 100644 --- a/src/test/ui/fmt/format-string-error.stderr +++ b/src/test/ui/fmt/format-string-error.stderr @@ -107,11 +107,5 @@ LL | } | = note: if you intended to print `}`, you can escape it using `}}` -error: 3 positional arguments in format string, but there are 2 arguments - --> $DIR/format-string-error.rs:51:15 - | -LL | println!("{} {} {}", 1, 2); - | ^^ ^^ ^^ - - - -error: aborting due to 13 previous errors +error: aborting due to 12 previous errors diff --git a/src/test/ui/for-loop-while/loop-break-value.rs b/src/test/ui/for-loop-while/loop-break-value.rs index d7209fc4de867..e1edbbb929e6a 100644 --- a/src/test/ui/for-loop-while/loop-break-value.rs +++ b/src/test/ui/for-loop-while/loop-break-value.rs @@ -1,5 +1,4 @@ // run-pass - #![allow(unreachable_code)] #![feature(never_type)] diff --git a/src/test/ui/gated-bad-feature.stderr b/src/test/ui/gated-bad-feature.stderr index 79e59f76311fd..ff6780e66a8ce 100644 --- a/src/test/ui/gated-bad-feature.stderr +++ b/src/test/ui/gated-bad-feature.stderr @@ -30,5 +30,4 @@ LL | #![feature = "foo"] error: aborting due to 5 previous errors -Some errors have detailed explanations: E0556, E0557. -For more information about an error, try `rustc --explain E0556`. +For more information about this error, try `rustc --explain E0557`. diff --git a/src/test/ui/generator/issue-58888.rs b/src/test/ui/generator/issue-58888.rs index d42d09d401e87..43b37a9afc2cc 100644 --- a/src/test/ui/generator/issue-58888.rs +++ b/src/test/ui/generator/issue-58888.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet #![feature(generators, generator_trait)] diff --git a/src/test/ui/generator/panic-drops.rs b/src/test/ui/generator/panic-drops.rs index b1a5cc67e86b3..5ac97585f4b57 100644 --- a/src/test/ui/generator/panic-drops.rs +++ b/src/test/ui/generator/panic-drops.rs @@ -1,6 +1,6 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled as panic=abort by default #![feature(generators, generator_trait)] diff --git a/src/test/ui/generator/panic-safe.rs b/src/test/ui/generator/panic-safe.rs index 06c026180190a..5f6778674dce1 100644 --- a/src/test/ui/generator/panic-safe.rs +++ b/src/test/ui/generator/panic-safe.rs @@ -1,6 +1,6 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait)] diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.polonius.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.polonius.stderr new file mode 100644 index 0000000000000..530bf368f676e --- /dev/null +++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.polonius.stderr @@ -0,0 +1,20 @@ +error[E0597]: `b` does not live long enough + --> $DIR/ref-escapes-but-not-over-yield.rs:11:13 + | +LL | let mut b = move || { + | _________________- +LL | | yield(); +LL | | let b = 5; +LL | | a = &b; + | | ^^ borrowed value does not live long enough +LL | | +LL | | }; + | | - + | | | + | | `b` dropped here while still borrowed + | |_____... and the borrow might be used here, when that temporary is dropped and runs the destructor for generator + | a temporary with access to the borrow is created here ... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/generator/resume-after-return.rs b/src/test/ui/generator/resume-after-return.rs index ab18be58155df..71a68ff684af3 100644 --- a/src/test/ui/generator/resume-after-return.rs +++ b/src/test/ui/generator/resume-after-return.rs @@ -1,6 +1,6 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait)] diff --git a/src/test/ui/generator/size-moved-locals.rs b/src/test/ui/generator/size-moved-locals.rs index 2864fbb2f3c8d..01db971434bbc 100644 --- a/src/test/ui/generator/size-moved-locals.rs +++ b/src/test/ui/generator/size-moved-locals.rs @@ -11,7 +11,6 @@ // edition:2018 // ignore-wasm32 issue #62807 -// ignore-asmjs issue #62807 #![feature(generators, generator_trait)] diff --git a/src/test/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.rs b/src/test/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.rs deleted file mode 100644 index cc93794e8fcdc..0000000000000 --- a/src/test/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![crate_type="lib"] - -// rust-lang/rust#61631: The use of `Self` in the defaults of generic -// types in a *trait* definition are allowed. -// -// It *must* be accepted; we have used this pattern extensively since -// Rust 1.0 (see e.g. `trait Add`). -trait Tnobound

{} - -impl Tnobound for () { } - -// This variant is accepted at the definition site; but it will be -// rejected at every possible usage site (such as the one immediately -// below). Maybe one day we will attempt to catch it at the definition -// site, but today this is accepted due to compiler implementation -// limitations. -trait Tsized {} - -impl Tsized for () {} -//~^ ERROR the size for values of type `[()]` cannot be known at compilation time [E0277] diff --git a/src/test/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr b/src/test/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr deleted file mode 100644 index ea0664c48d4d8..0000000000000 --- a/src/test/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0277]: the size for values of type `[()]` cannot be known at compilation time - --> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:19:6 - | -LL | impl Tsized for () {} - | ^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `std::marker::Sized` is not implemented for `[()]` - = note: to learn more, visit - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs b/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs deleted file mode 100644 index b560cc2ce7060..0000000000000 --- a/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs +++ /dev/null @@ -1,45 +0,0 @@ -#![crate_type="lib"] - -// rust-lang/rust#61631: Uses of `Self` in the defaults of generic -// types for ADT's are not allowed. We justify this because the `Self` -// type could be considered the "final" type parameter, that is only -// well-defined after all of the other type parameters on the ADT have -// been instantiated. -// -// These were previously were ICE'ing at the usage point anyway (see -// `demo_usages` below), so there should not be any backwards -// compatibility concern. - -struct Snobound<'a, P = Self> { x: Option<&'a P> } -//~^ ERROR type parameters cannot use `Self` in their defaults [E0735] - -enum Enobound<'a, P = Self> { A, B(Option<&'a P>) } -//~^ ERROR type parameters cannot use `Self` in their defaults [E0735] - -union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> } -//~^ ERROR type parameters cannot use `Self` in their defaults [E0735] - -// Disallowing `Self` in defaults sidesteps need to check the bounds -// on the defaults in cases like these. - -struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> } -//~^ ERROR type parameters cannot use `Self` in their defaults [E0735] - -enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) } -//~^ ERROR type parameters cannot use `Self` in their defaults [E0735] - -union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> } -//~^ ERROR type parameters cannot use `Self` in their defaults [E0735] - -fn demo_usages() { - // An ICE means you only get the error from the first line of the - // demo; comment each out to observe the other ICEs when trying - // this out on older versions of Rust. - - let _ice: Snobound; - let _ice: Enobound; - let _ice: Unobound; - let _ice: Ssized; - let _ice: Esized; - let _ice: Usized; -} diff --git a/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr b/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr deleted file mode 100644 index 689ffbd0febc2..0000000000000 --- a/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0735]: type parameters cannot use `Self` in their defaults - --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:13:25 - | -LL | struct Snobound<'a, P = Self> { x: Option<&'a P> } - | ^^^^ `Self` in type parameter default - -error[E0735]: type parameters cannot use `Self` in their defaults - --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:16:23 - | -LL | enum Enobound<'a, P = Self> { A, B(Option<&'a P>) } - | ^^^^ `Self` in type parameter default - -error[E0735]: type parameters cannot use `Self` in their defaults - --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:19:24 - | -LL | union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> } - | ^^^^ `Self` in type parameter default - -error[E0735]: type parameters cannot use `Self` in their defaults - --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:25:31 - | -LL | struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> } - | ^^^^ `Self` in type parameter default - -error[E0735]: type parameters cannot use `Self` in their defaults - --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:28:29 - | -LL | enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) } - | ^^^^ `Self` in type parameter default - -error[E0735]: type parameters cannot use `Self` in their defaults - --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:31:30 - | -LL | union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> } - | ^^^^ `Self` in type parameter default - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0735`. diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs deleted file mode 100644 index 54b483f53d4cb..0000000000000 --- a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![crate_type="lib"] - -struct Nested(K); - -fn should_error() where T : Into<&u32> {} -//~^ ERROR `&` without an explicit lifetime name cannot be used here [E0637] - -trait X<'a, K: 'a> { - fn foo<'b, L: X<&'b Nested>>(); - //~^ ERROR missing lifetime specifier [E0106] -} - -fn bar<'b, L: X<&'b Nested>>(){} -//~^ ERROR missing lifetime specifier [E0106] diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr deleted file mode 100644 index 8720288b53e58..0000000000000 --- a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:5:37 - | -LL | fn should_error() where T : Into<&u32> {} - | ^ explicit lifetime name needed here - -error[E0106]: missing lifetime specifier - --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:19 - | -LL | fn foo<'b, L: X<&'b Nested>>(); - | ^^^^^^^^^^^^^^^^ expected lifetime parameter - -error[E0106]: missing lifetime specifier - --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:15 - | -LL | fn bar<'b, L: X<&'b Nested>>(){} - | ^^^^^^^^^^^^^^^^^^ expected lifetime parameter - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr index 76d97dd2f585d..979f64fcd90a5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr @@ -10,7 +10,7 @@ LL | | fn(Inv<'y>)) } | = note: expected type `std::option::Option)>` found type `std::option::Option)>` -note: the lifetime `'x` as defined on the function body at 32:20... +note: the lifetime 'x as defined on the function body at 32:20... --> $DIR/hr-subtype.rs:32:20 | LL | fn subtype<'x,'y:'x,'z:'y>() { @@ -19,7 +19,7 @@ LL | fn subtype<'x,'y:'x,'z:'y>() { LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), LL | | fn(Inv<'y>)) } | |__________________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 32:23 +note: ...does not necessarily outlive the lifetime 'y as defined on the function body at 32:23 --> $DIR/hr-subtype.rs:32:23 | LL | fn subtype<'x,'y:'x,'z:'y>() { @@ -41,7 +41,7 @@ LL | | fn(Inv<'y>)) } | = note: expected type `std::option::Option)>` found type `std::option::Option)>` -note: the lifetime `'x` as defined on the function body at 38:22... +note: the lifetime 'x as defined on the function body at 38:22... --> $DIR/hr-subtype.rs:38:22 | LL | fn supertype<'x,'y:'x,'z:'y>() { @@ -50,7 +50,7 @@ LL | fn supertype<'x,'y:'x,'z:'y>() { LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), LL | | fn(Inv<'y>)) } | |__________________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25 +note: ...does not necessarily outlive the lifetime 'y as defined on the function body at 38:25 --> $DIR/hr-subtype.rs:38:25 | LL | fn supertype<'x,'y:'x,'z:'y>() { diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr index 74f4212b2468b..3b6aff5216989 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr @@ -10,7 +10,7 @@ LL | | fn(&'y u32)) } | = note: expected type `std::option::Option` found type `std::option::Option` -note: the lifetime `'x` as defined on the function body at 38:22... +note: the lifetime 'x as defined on the function body at 38:22... --> $DIR/hr-subtype.rs:38:22 | LL | fn supertype<'x,'y:'x,'z:'y>() { @@ -19,7 +19,7 @@ LL | fn supertype<'x,'y:'x,'z:'y>() { LL | / check! { free_x_vs_free_y: (fn(&'x u32), LL | | fn(&'y u32)) } | |__________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25 +note: ...does not necessarily outlive the lifetime 'y as defined on the function body at 38:25 --> $DIR/hr-subtype.rs:38:25 | LL | fn supertype<'x,'y:'x,'z:'y>() { diff --git a/src/test/ui/hrtb/due-to-where-clause.nll.stderr b/src/test/ui/hrtb/due-to-where-clause.nll.stderr deleted file mode 100644 index e476047a7a644..0000000000000 --- a/src/test/ui/hrtb/due-to-where-clause.nll.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: higher-ranked subtype error - --> $DIR/due-to-where-clause.rs:2:5 - | -LL | test::(&mut 42); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/hrtb/due-to-where-clause.rs b/src/test/ui/hrtb/due-to-where-clause.rs index 1afd15613b51c..04e2ddd4a6090 100644 --- a/src/test/ui/hrtb/due-to-where-clause.rs +++ b/src/test/ui/hrtb/due-to-where-clause.rs @@ -1,3 +1,6 @@ +// ignore-compare-mode-nll +// ^ This code works in nll mode. + fn main() { test::(&mut 42); //~ ERROR implementation of `Foo` is not general enough } diff --git a/src/test/ui/hrtb/due-to-where-clause.stderr b/src/test/ui/hrtb/due-to-where-clause.stderr index e4096ec059a6e..9fef1e3354399 100644 --- a/src/test/ui/hrtb/due-to-where-clause.stderr +++ b/src/test/ui/hrtb/due-to-where-clause.stderr @@ -1,5 +1,5 @@ error: implementation of `Foo` is not general enough - --> $DIR/due-to-where-clause.rs:2:5 + --> $DIR/due-to-where-clause.rs:5:5 | LL | test::(&mut 42); | ^^^^^^^^^^^^ implementation of `Foo` is not general enough 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 afcb467ad4711..c2cc8ebad2726 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr @@ -6,11 +6,10 @@ 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 | where B : Qux - | - help: consider further restricting type parameter `B`: `, for<'ccx> B: Bar<'ccx>` -... LL | want_bar_for_any_ccx(b); | ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | + = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound 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 20913b4f28c8e..a93814ad4c25e 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr @@ -1,9 +1,6 @@ error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:18:26 | -LL | where F : Foo<'x> - | - help: consider further restricting type parameter `F`: `, for<'tcx> F: Foo<'tcx>` -... LL | want_foo_for_any_tcx(f); | ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` ... @@ -11,13 +8,12 @@ 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 error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26 | -LL | where B : Bar<'x> - | - help: consider further restricting type parameter `B`: `, for<'ccx> B: Bar<'ccx>` -... LL | want_bar_for_any_ccx(b); | ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` ... @@ -25,6 +21,8 @@ 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 error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr index cd1272da2a66e..1cfd93e59d935 100644 --- a/src/test/ui/hrtb/issue-30786.nll.stderr +++ b/src/test/ui/hrtb/issue-30786.nll.stderr @@ -1,20 +1,14 @@ error: higher-ranked subtype error - --> $DIR/issue-30786.rs:108:15 - | -LL | let map = source.map(|x: &_| x); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 + --> $DIR/issue-30786.rs:113:18 | LL | let filter = map.filter(|x: &_| true); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: higher-ranked subtype error - --> $DIR/issue-30786.rs:116:17 + --> $DIR/issue-30786.rs:115:17 | LL | let count = filter.count(); // Assert that we still have a valid stream. | ^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs index 34d6b19f602f7..c42297ca68346 100644 --- a/src/test/ui/hrtb/issue-30786.rs +++ b/src/test/ui/hrtb/issue-30786.rs @@ -106,8 +106,7 @@ impl StreamExt for T where for<'a> &'a mut T: Stream { } fn main() { let source = Repeat(10); let map = source.map(|x: &_| x); - //[nll]~^ ERROR higher-ranked subtype error - //[migrate]~^^ ERROR implementation of `Stream` is not general enough + //[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 @@ -115,5 +114,4 @@ fn main() { //[nll]~^ ERROR higher-ranked subtype error let count = filter.count(); // Assert that we still have a valid stream. //[nll]~^ ERROR higher-ranked subtype error - } diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr index 7acb266f49c0b..7e0f4e4e0b8f3 100644 --- a/src/test/ui/hygiene/globs.stderr +++ b/src/test/ui/hygiene/globs.stderr @@ -34,7 +34,7 @@ LL | use foo::test2::test::g; | LL | use foo::test::g; | - and 2 other candidates +and 2 other candidates error[E0425]: cannot find function `f` in this scope --> $DIR/globs.rs:61:12 diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr index 736369dab8354..bc0ce746be925 100644 --- a/src/test/ui/hygiene/no_implicit_prelude.stderr +++ b/src/test/ui/hygiene/no_implicit_prelude.stderr @@ -25,7 +25,7 @@ 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: + = note: the following trait is implemented but not in scope, perhaps add a `use` for it: `use std::clone::Clone;` error: aborting due to 3 previous errors diff --git a/src/test/ui/hygiene/rustc-macro-transparency.stderr b/src/test/ui/hygiene/rustc-macro-transparency.stderr index 45a2efebbb8da..5eacfdf8dee13 100644 --- a/src/test/ui/hygiene/rustc-macro-transparency.stderr +++ b/src/test/ui/hygiene/rustc-macro-transparency.stderr @@ -2,7 +2,7 @@ error[E0425]: cannot find value `Opaque` in this scope --> $DIR/rustc-macro-transparency.rs:26:5 | LL | Opaque; - | ^^^^^^ help: a local variable with a similar name exists (notice the capitalization): `opaque` + | ^^^^^^ help: a local variable with a similar name exists: `opaque` error[E0423]: expected value, found macro `semitransparent` --> $DIR/rustc-macro-transparency.rs:29:5 diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr index c3ce484edf7a9..39e32522c7a76 100644 --- a/src/test/ui/hygiene/trait_items.stderr +++ b/src/test/ui/hygiene/trait_items.stderr @@ -8,7 +8,7 @@ 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: + = note: the following trait is implemented but not in scope, perhaps add a `use` for it: `use foo::T;` error: aborting due to previous error diff --git a/src/test/ui/hygiene/unpretty-debug.stdout b/src/test/ui/hygiene/unpretty-debug.stdout index acd852103cae3..6971873ba601e 100644 --- a/src/test/ui/hygiene/unpretty-debug.stdout +++ b/src/test/ui/hygiene/unpretty-debug.stdout @@ -17,7 +17,7 @@ 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") +1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, foo) SyntaxContexts: #0: parent: #0, outer_mark: (ExpnId(0), Opaque) diff --git a/src/test/ui/if/if-no-match-bindings.stderr b/src/test/ui/if/if-no-match-bindings.stderr index 0936f3b9e38e8..cbf52476ae37f 100644 --- a/src/test/ui/if/if-no-match-bindings.stderr +++ b/src/test/ui/if/if-no-match-bindings.stderr @@ -2,10 +2,7 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:18:8 | LL | if b_ref() {} - | ^^^^^^^ - | | - | expected bool, found &bool - | help: consider dereferencing the borrow: `*b_ref()` + | ^^^^^^^ expected bool, found &bool | = note: expected type `bool` found type `&bool` @@ -14,10 +11,7 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:19:8 | LL | if b_mut_ref() {} - | ^^^^^^^^^^^ - | | - | expected bool, found &mut bool - | help: consider dereferencing the borrow: `*b_mut_ref()` + | ^^^^^^^^^^^ expected bool, found &mut bool | = note: expected type `bool` found type `&mut bool` @@ -26,10 +20,7 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:20:8 | LL | if &true {} - | ^^^^^ - | | - | expected bool, found &bool - | help: consider removing the borrow: `true` + | ^^^^^ expected bool, found &bool | = note: expected type `bool` found type `&bool` @@ -38,10 +29,7 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:21:8 | LL | if &mut true {} - | ^^^^^^^^^ - | | - | expected bool, found &mut bool - | help: consider removing the borrow: `true` + | ^^^^^^^^^ expected bool, found &mut bool | = note: expected type `bool` found type `&mut bool` @@ -50,10 +38,7 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:24:11 | LL | while b_ref() {} - | ^^^^^^^ - | | - | expected bool, found &bool - | help: consider dereferencing the borrow: `*b_ref()` + | ^^^^^^^ expected bool, found &bool | = note: expected type `bool` found type `&bool` @@ -62,10 +47,7 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:25:11 | LL | while b_mut_ref() {} - | ^^^^^^^^^^^ - | | - | expected bool, found &mut bool - | help: consider dereferencing the borrow: `*b_mut_ref()` + | ^^^^^^^^^^^ expected bool, found &mut bool | = note: expected type `bool` found type `&mut bool` @@ -74,10 +56,7 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:26:11 | LL | while &true {} - | ^^^^^ - | | - | expected bool, found &bool - | help: consider removing the borrow: `true` + | ^^^^^ expected bool, found &bool | = note: expected type `bool` found type `&bool` @@ -86,10 +65,7 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:27:11 | LL | while &mut true {} - | ^^^^^^^^^ - | | - | expected bool, found &mut bool - | help: consider removing the borrow: `true` + | ^^^^^^^^^ expected bool, found &mut bool | = note: expected type `bool` found type `&mut bool` diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr index c58cbc312335a..336ea2254bf5a 100644 --- a/src/test/ui/if/ifmt-bad-arg.stderr +++ b/src/test/ui/if/ifmt-bad-arg.stderr @@ -224,9 +224,8 @@ error: 4 positional arguments in format string, but there are 3 arguments --> $DIR/ifmt-bad-arg.rs:78:15 | LL | println!("{} {:.*} {}", 1, 3.2, 4); - | ^^ ^^--^ ^^ - --- - - | | | - | | this parameter corresponds to the precision flag + | ^^ ^^--^ ^^ --- this parameter corresponds to the precision flag + | | | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected | = note: positional arguments are zero-based @@ -236,9 +235,8 @@ error: 4 positional arguments in format string, but there are 3 arguments --> $DIR/ifmt-bad-arg.rs:81:15 | LL | println!("{} {:07$.*} {}", 1, 3.2, 4); - | ^^ ^^^----^ ^^ - --- - - | | | | - | | | this parameter corresponds to the precision flag + | ^^ ^^^----^ ^^ --- this parameter corresponds to the precision flag + | | | | | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected | this width flag expects an `usize` argument at position 7, but there are 3 arguments | diff --git a/src/test/ui/never_type/impl-for-never.rs b/src/test/ui/impl-for-never.rs similarity index 99% rename from src/test/ui/never_type/impl-for-never.rs rename to src/test/ui/impl-for-never.rs index 9423f08858b9b..c5f12981ecc26 100644 --- a/src/test/ui/never_type/impl-for-never.rs +++ b/src/test/ui/impl-for-never.rs @@ -1,9 +1,8 @@ // run-pass +// Test that we can call static methods on ! both directly and when it appears in a generic #![feature(never_type)] -// Test that we can call static methods on ! both directly and when it appears in a generic - trait StringifyType { fn stringify_type() -> &'static str; } diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr index 5e80c673258b8..eb824def24687 100644 --- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr +++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | static_val(x); | ^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 19:26... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 19:26... --> $DIR/dyn-trait.rs:19:26 | LL | fn with_dyn_debug_static<'a>(x: Box) { @@ -19,4 +19,3 @@ LL | fn with_dyn_debug_static<'a>(x: Box) { error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr index 956ac1f1a1167..650161753d1e5 100644 --- a/src/test/ui/impl-trait/hidden-lifetimes.stderr +++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr @@ -4,7 +4,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { | ^^^^^^^^^^^^^^ | -note: hidden type `&'a mut &'b T` captures the lifetime `'b` as defined on the function body at 28:17 +note: hidden type `&'a mut &'b T` captures the lifetime 'b as defined on the function body at 28:17 --> $DIR/hidden-lifetimes.rs:28:17 | LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { @@ -16,7 +16,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { | ^^^^^^^^^^^^^^ | -note: hidden type `std::rc::Rc>` captures the lifetime `'b` as defined on the function body at 45:24 +note: hidden type `std::rc::Rc>` captures the lifetime 'b as defined on the function body at 45:24 --> $DIR/hidden-lifetimes.rs:45:24 | LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr index 0d8ee61b5ba13..d5756c015596e 100644 --- a/src/test/ui/impl-trait/issue-55872-1.stderr +++ b/src/test/ui/impl-trait/issue-55872-1.stderr @@ -1,11 +1,10 @@ error[E0277]: the trait bound `S: std::marker::Copy` is not satisfied in `(S, T)` --> $DIR/issue-55872-1.rs:12:5 | -LL | impl Bar for S { - | -- help: consider further restricting this bound: `S: std::marker::Copy +` LL | type E = impl Copy; | ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `S` | + = help: consider adding a `where S: std::marker::Copy` bound = note: required because it appears within the type `(S, T)` = note: the return type of a function must have a statically known size @@ -14,10 +13,8 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied in `(S, T) | LL | type E = impl Copy; | ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `T` -... -LL | fn foo() -> Self::E { - | -- help: consider further restricting this bound: `T: std::marker::Copy +` | + = help: consider adding a `where T: std::marker::Copy` bound = note: required because it appears within the type `(S, T)` = note: the return type of a function must have a statically known size diff --git a/src/test/ui/impl-trait/issues/universal-issue-48703.rs b/src/test/ui/impl-trait/issues/universal-issue-48703.rs index f661c62c9e440..e434e10bf89d7 100644 --- a/src/test/ui/impl-trait/issues/universal-issue-48703.rs +++ b/src/test/ui/impl-trait/issues/universal-issue-48703.rs @@ -5,5 +5,5 @@ use std::fmt::Debug; fn foo(x: impl Debug) { } fn main() { - foo::('a'); //~ ERROR cannot provide explicit generic arguments + foo::('a'); //~ ERROR cannot provide explicit type parameters } diff --git a/src/test/ui/impl-trait/issues/universal-issue-48703.stderr b/src/test/ui/impl-trait/issues/universal-issue-48703.stderr index 8f05ab3c4940c..527bbd5f30fef 100644 --- a/src/test/ui/impl-trait/issues/universal-issue-48703.stderr +++ b/src/test/ui/impl-trait/issues/universal-issue-48703.stderr @@ -1,8 +1,8 @@ -error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> $DIR/universal-issue-48703.rs:8:11 +error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position. + --> $DIR/universal-issue-48703.rs:8:5 | LL | foo::('a'); - | ^^^^^^ explicit generic argument not allowed + | ^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.rs b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.rs index 4ac0a694cb148..d3d561621fc2d 100644 --- a/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.rs +++ b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.rs @@ -12,6 +12,6 @@ struct TestEvent(i32); fn main() { let mut evt = EventHandler {}; evt.handle_event::(|_evt| { - //~^ ERROR cannot provide explicit generic arguments + //~^ ERROR cannot provide explicit type parameters }); } diff --git a/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr index c980e9463e48a..e2e6581fcf915 100644 --- a/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr +++ b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr @@ -1,10 +1,8 @@ -error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> $DIR/universal-turbofish-in-method-issue-50950.rs:14:24 +error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position. + --> $DIR/universal-turbofish-in-method-issue-50950.rs:14:9 | LL | evt.handle_event::(|_evt| { - | ^^^^^^^^^ ^^^^^^^^^^^^^ explicit generic argument not allowed - | | - | explicit generic argument not allowed + | ^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 2ffb94348616b..a6ea7837678ed 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -24,12 +24,12 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | | | this return type evaluates to the `'static` lifetime... | -note: ...can't outlive the lifetime `'a` as defined on the function body at 6:13 +note: ...can't outlive the lifetime 'a as defined on the function body at 6:13 --> $DIR/must_outlive_least_region_or_bound.rs:6:13 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ^^ -help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 6:13 +help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the function body at 6:13 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^^^^^^^^^^^ @@ -42,12 +42,12 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | | | this return type evaluates to the `'static` lifetime... | -note: ...can't outlive the lifetime `'a` as defined on the function body at 12:15 +note: ...can't outlive the lifetime 'a as defined on the function body at 12:15 --> $DIR/must_outlive_least_region_or_bound.rs:12:15 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ^^ -help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 12:15 +help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the function body at 12:15 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 f0a03e1be82ac..be8f3ab1b72e8 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -5,7 +5,7 @@ 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: +help: the following traits are implemented but not in scope, perhaps add a `use` for one of them: | LL | use foo::Bar; | @@ -23,7 +23,7 @@ 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: +help: the following traits are implemented but not in scope, perhaps add a `use` for one of them: | LL | use foo::Bar; | @@ -41,7 +41,7 @@ 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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use foo::Bar; | @@ -61,7 +61,7 @@ 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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use foo::Bar; | @@ -73,7 +73,7 @@ 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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use no_method_suggested_traits::foo::PubPub; | @@ -85,7 +85,7 @@ 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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use no_method_suggested_traits::foo::PubPub; | diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr index 894a65ff38995..5c8e322f712d1 100644 --- a/src/test/ui/impl-trait/region-escape-via-bound.stderr +++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr @@ -4,7 +4,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y> | ^^^^^^^^^^^^^^ | -note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime `'x` as defined on the function body at 17:7 +note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime 'x as defined on the function body at 17:7 --> $DIR/region-escape-via-bound.rs:17:7 | LL | where 'x: 'y diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 1d6b5f56aa0cf..0bc0180e78a42 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -30,12 +30,12 @@ LL | self.x.iter().map(|a| a.0) | | | ...but this borrow... | -note: ...can't outlive the lifetime `'a` as defined on the method body at 10:20 +note: ...can't outlive the lifetime 'a as defined on the method body at 10:20 --> $DIR/static-return-lifetime-infered.rs:10:20 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { | ^^ -help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the method body at 10:20 +help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the method body at 10:20 | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr index c1ec536ef4362..b50a926c63795 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr @@ -18,4 +18,3 @@ LL | | } error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr index b5287f32a5045..cd65bab2d4668 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr @@ -11,7 +11,7 @@ LL | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { LL | | x LL | | } | |_____^ -note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32... +note: ...but the lifetime must also be valid for the lifetime 'a as defined on the method body at 9:32... --> $DIR/mismatched_trait_impl.rs:9:32 | LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { @@ -22,4 +22,3 @@ LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr index 734ca0819e416..80f15b7c5847f 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -11,7 +11,7 @@ LL | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { LL | | x LL | | } | |_____^ -note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32... +note: ...but the lifetime must also be valid for the lifetime 'a as defined on the method body at 9:32... --> $DIR/mismatched_trait_impl.rs:9:32 | LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { @@ -32,4 +32,3 @@ LL | x error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/include-single-expr-helper-1.rs b/src/test/ui/include-single-expr-helper-1.rs deleted file mode 100644 index aa6380bd24dc7..0000000000000 --- a/src/test/ui/include-single-expr-helper-1.rs +++ /dev/null @@ -1,5 +0,0 @@ -// ignore-test auxiliary file for include-single-expr.rs - -0 - -// trailing comment permitted diff --git a/src/test/ui/include-single-expr-helper.rs b/src/test/ui/include-single-expr-helper.rs deleted file mode 100644 index 84d8b69603b6b..0000000000000 --- a/src/test/ui/include-single-expr-helper.rs +++ /dev/null @@ -1,5 +0,0 @@ -// ignore-test auxiliary file for include-single-expr.rs - -0 -10 -100 diff --git a/src/test/ui/include-single-expr.rs b/src/test/ui/include-single-expr.rs deleted file mode 100644 index 0f4c29ec01456..0000000000000 --- a/src/test/ui/include-single-expr.rs +++ /dev/null @@ -1,6 +0,0 @@ -// error-pattern include macro expected single expression - -fn main() { - include!("include-single-expr-helper.rs"); - include!("include-single-expr-helper-1.rs"); -} diff --git a/src/test/ui/include-single-expr.stderr b/src/test/ui/include-single-expr.stderr deleted file mode 100644 index 80eecf8f1b979..0000000000000 --- a/src/test/ui/include-single-expr.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: include macro expected single expression in source - --> $DIR/include-single-expr-helper.rs:4:1 - | -LL | 10 - | ^^ - | - = note: `#[deny(incomplete_include)]` on by default - -error: aborting due to previous error - diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr index f4567554d0dbb..a2ad58a7e46fc 100644 --- a/src/test/ui/infinite/infinite-autoderef.stderr +++ b/src/test/ui/infinite/infinite-autoderef.stderr @@ -5,7 +5,7 @@ LL | x = box x; | ^^^^^ | | | cyclic type of infinite size - | help: try using a conversion method: `(box x).to_string()` + | help: try using a conversion method: `box x.to_string()` error[E0055]: reached the recursion limit while auto-dereferencing `Foo` --> $DIR/infinite-autoderef.rs:25:5 diff --git a/src/test/ui/inner-static-type-parameter.stderr b/src/test/ui/inner-static-type-parameter.stderr index 1e74445af55cb..083b4b67eb459 100644 --- a/src/test/ui/inner-static-type-parameter.stderr +++ b/src/test/ui/inner-static-type-parameter.stderr @@ -2,7 +2,9 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/inner-static-type-parameter.rs:6:19 | LL | fn foo() { - | - type parameter from outer function + | --- - type parameter from outer function + | | + | try adding a local generic parameter in this method instead LL | static a: Bar = Bar::What; | ^ use of generic parameter from outer function @@ -12,7 +14,7 @@ error[E0392]: parameter `T` is never used LL | enum Bar { What } | ^ unused parameter | - = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `T` or using a marker such as `std::marker::PhantomData` error: aborting due to 2 previous errors diff --git a/src/test/ui/intrinsics/intrinsic-alignment.rs b/src/test/ui/intrinsics/intrinsic-alignment.rs index 02e3139d29444..6a67d04a54cf4 100644 --- a/src/test/ui/intrinsics/intrinsic-alignment.rs +++ b/src/test/ui/intrinsics/intrinsic-alignment.rs @@ -19,8 +19,7 @@ mod rusti { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris", - target_os = "vxworks"))] + target_os = "solaris"))] mod m { #[main] #[cfg(target_arch = "x86")] diff --git a/src/test/ui/intrinsics/intrinsics-integer.rs b/src/test/ui/intrinsics/intrinsics-integer.rs index bac6c8d872b40..0154f04995029 100644 --- a/src/test/ui/intrinsics/intrinsics-integer.rs +++ b/src/test/ui/intrinsics/intrinsics-integer.rs @@ -1,4 +1,5 @@ // run-pass +// ignore-emscripten no i128 support #![feature(intrinsics)] diff --git a/src/test/ui/invalid/invalid-plugin-attr.rs b/src/test/ui/invalid/invalid-plugin-attr.rs index 3ba7389d5db69..2cbd523386148 100644 --- a/src/test/ui/invalid/invalid-plugin-attr.rs +++ b/src/test/ui/invalid/invalid-plugin-attr.rs @@ -3,6 +3,5 @@ #[plugin(bla)] //~ ERROR unused attribute //~^ ERROR should be an inner attribute -//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated fn main() {} diff --git a/src/test/ui/invalid/invalid-plugin-attr.stderr b/src/test/ui/invalid/invalid-plugin-attr.stderr index 0d7315dd887ca..36714c39b315a 100644 --- a/src/test/ui/invalid/invalid-plugin-attr.stderr +++ b/src/test/ui/invalid/invalid-plugin-attr.stderr @@ -1,11 +1,3 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/invalid-plugin-attr.rs:4:1 - | -LL | #[plugin(bla)] - | ^^^^^^^^^^^^^^ help: may be removed in a future compiler version - | - = note: `#[warn(deprecated)]` on by default - error: unused attribute --> $DIR/invalid-plugin-attr.rs:4:1 | diff --git a/src/test/ui/issues/issue-53912.rs b/src/test/ui/issue-53912.rs similarity index 100% rename from src/test/ui/issues/issue-53912.rs rename to src/test/ui/issue-53912.rs diff --git a/src/test/ui/issues/issue-59020.rs b/src/test/ui/issue-59020.rs similarity index 100% rename from src/test/ui/issues/issue-59020.rs rename to src/test/ui/issue-59020.rs diff --git a/src/test/ui/issues/auxiliary/issue-57271-lib.rs b/src/test/ui/issues/auxiliary/issue-57271-lib.rs deleted file mode 100644 index ff625668a9ddf..0000000000000 --- a/src/test/ui/issues/auxiliary/issue-57271-lib.rs +++ /dev/null @@ -1,11 +0,0 @@ -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] -pub enum BaseType { - Byte, - Char, - Double, - Float, - Int, - Long, - Short, - Boolean, -} diff --git a/src/test/ui/issues/issue-10200.stderr b/src/test/ui/issues/issue-10200.stderr index b1057d45869a8..544716e89b39d 100644 --- a/src/test/ui/issues/issue-10200.stderr +++ b/src/test/ui/issues/issue-10200.stderr @@ -2,7 +2,7 @@ error[E0532]: expected tuple struct/variant, found function `foo` --> $DIR/issue-10200.rs:6:9 | LL | foo(x) - | ^^^ help: a tuple struct with a similar name exists (notice the capitalization): `Foo` + | ^^^ help: a tuple struct with a similar name exists: `Foo` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-10291.stderr b/src/test/ui/issues/issue-10291.stderr index 4fff4ee866c39..a836593e0da10 100644 --- a/src/test/ui/issues/issue-10291.stderr +++ b/src/test/ui/issues/issue-10291.stderr @@ -12,7 +12,7 @@ LL | drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { LL | | x LL | | })); | |_____^ -note: ...but the borrowed content is only valid for the lifetime `'x` as defined on the function body at 1:9 +note: ...but the borrowed content is only valid for the lifetime 'x as defined on the function body at 1:9 --> $DIR/issue-10291.rs:1:9 | LL | fn test<'x>(x: &'x isize) { diff --git a/src/test/ui/issues/issue-10465.stderr b/src/test/ui/issues/issue-10465.stderr index 80ca051ceff0d..413daa6db6787 100644 --- a/src/test/ui/issues/issue-10465.stderr +++ b/src/test/ui/issues/issue-10465.stderr @@ -5,7 +5,7 @@ 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: + = note: the following trait is implemented but not in scope, perhaps add a `use` for it: `use a::A;` error: aborting due to previous error diff --git a/src/test/ui/never_type/issue-13352.rs b/src/test/ui/issues/issue-13352.rs similarity index 100% rename from src/test/ui/never_type/issue-13352.rs rename to src/test/ui/issues/issue-13352.rs diff --git a/src/test/ui/never_type/issue-13352.stderr b/src/test/ui/issues/issue-13352.stderr similarity index 100% rename from src/test/ui/never_type/issue-13352.stderr rename to src/test/ui/issues/issue-13352.stderr diff --git a/src/test/ui/issues/issue-13867.rs b/src/test/ui/issues/issue-13867.rs index 9510aae775341..e66368f9ba8fa 100644 --- a/src/test/ui/issues/issue-13867.rs +++ b/src/test/ui/issues/issue-13867.rs @@ -2,6 +2,7 @@ // Test that codegen works correctly when there are multiple refutable // patterns in match expression. + enum Foo { FooUint(usize), FooNullary, diff --git a/src/test/ui/issues/issue-14875.rs b/src/test/ui/issues/issue-14875.rs index 29e974ad83d1e..a2fd796245822 100644 --- a/src/test/ui/issues/issue-14875.rs +++ b/src/test/ui/issues/issue-14875.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare always compiled as panic=abort right now // Check that values are not leaked when a dtor panics (#14875) diff --git a/src/test/ui/issues/issue-16683.stderr b/src/test/ui/issues/issue-16683.stderr index b663e213ed05e..771a2ddf240f5 100644 --- a/src/test/ui/issues/issue-16683.stderr +++ b/src/test/ui/issues/issue-16683.stderr @@ -16,7 +16,7 @@ note: ...so that reference does not outlive borrowed content | LL | self.a(); | ^^^^ -note: but, the lifetime must be valid for the lifetime `'a` as defined on the trait at 1:9... +note: but, the lifetime must be valid for the lifetime 'a as defined on the trait at 1:9... --> $DIR/issue-16683.rs:1:9 | LL | trait T<'a> { @@ -27,4 +27,3 @@ LL | trait T<'a> { error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-17001.stderr b/src/test/ui/issues/issue-17001.stderr index d7e6069977b4e..2374e829556ec 100644 --- a/src/test/ui/issues/issue-17001.stderr +++ b/src/test/ui/issues/issue-17001.stderr @@ -6,4 +6,3 @@ LL | let p = foo { x: () }; error: aborting due to previous error -For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/issues/issue-17252.stderr b/src/test/ui/issues/issue-17252.stderr index 8fd67b19d6a5a..da3e2e763af58 100644 --- a/src/test/ui/issues/issue-17252.stderr +++ b/src/test/ui/issues/issue-17252.stderr @@ -1,11 +1,11 @@ -error[E0391]: cycle detected when const checking `FOO` +error[E0391]: cycle detected when processing `FOO` --> $DIR/issue-17252.rs:1:20 | LL | const FOO: usize = FOO; | ^^^ | - = note: ...which again requires const checking `FOO`, completing the cycle -note: cycle used when const checking `main::{{constant}}#0` + = note: ...which again requires processing `FOO`, completing the cycle +note: cycle used when processing `main::{{constant}}#0` --> $DIR/issue-17252.rs:4:18 | LL | let _x: [u8; FOO]; // caused stack overflow prior to fix diff --git a/src/test/ui/issues/issue-17405.stderr b/src/test/ui/issues/issue-17405.stderr index 37274e239ba0b..4b5678a88773b 100644 --- a/src/test/ui/issues/issue-17405.stderr +++ b/src/test/ui/issues/issue-17405.stderr @@ -6,4 +6,3 @@ LL | Foo { i } => () error: aborting due to previous error -For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr index 291086d4f694e..e27f49b4a3f0a 100644 --- a/src/test/ui/issues/issue-17546.stderr +++ b/src/test/ui/issues/issue-17546.stderr @@ -27,7 +27,7 @@ LL | use std::prelude::v1::Result; | LL | use std::result::Result; | - and 1 other candidate +and 1 other candidates error[E0573]: expected type, found variant `Result` --> $DIR/issue-17546.rs:28:13 @@ -44,7 +44,7 @@ LL | use std::prelude::v1::Result; | LL | use std::result::Result; | - and 1 other candidate +and 1 other candidates error[E0573]: expected type, found variant `NoResult` --> $DIR/issue-17546.rs:33:15 @@ -62,4 +62,3 @@ LL | fn newer() -> Result { error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/issues/issue-17718-const-naming.stderr b/src/test/ui/issues/issue-17718-const-naming.stderr index e320c436f5b68..1fe1821292c08 100644 --- a/src/test/ui/issues/issue-17718-const-naming.stderr +++ b/src/test/ui/issues/issue-17718-const-naming.stderr @@ -15,7 +15,7 @@ error: constant `foo` should have an upper case name --> $DIR/issue-17718-const-naming.rs:4:7 | LL | const foo: isize = 3; - | ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO` + | ^^^ help: convert the identifier to upper case: `FOO` | note: lint level defined here --> $DIR/issue-17718-const-naming.rs:2:9 diff --git a/src/test/ui/issues/issue-17740.stderr b/src/test/ui/issues/issue-17740.stderr index d392ea3c1b861..b8a0a0676319a 100644 --- a/src/test/ui/issues/issue-17740.stderr +++ b/src/test/ui/issues/issue-17740.stderr @@ -17,7 +17,7 @@ LL | | LL | | LL | | } | |_____^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 5:7 +note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 5:7 --> $DIR/issue-17740.rs:5:7 | LL | impl <'a> Foo<'a>{ @@ -31,7 +31,7 @@ LL | fn bar(self: &mut Foo) { | = note: expected type `Foo<'a>` found type `Foo<'_>` -note: the lifetime `'a` as defined on the impl at 5:7... +note: the lifetime 'a as defined on the impl at 5:7... --> $DIR/issue-17740.rs:5:7 | LL | impl <'a> Foo<'a>{ diff --git a/src/test/ui/issues/issue-17758.stderr b/src/test/ui/issues/issue-17758.stderr index adcbb62e3d5bd..0ef3b98719d34 100644 --- a/src/test/ui/issues/issue-17758.stderr +++ b/src/test/ui/issues/issue-17758.stderr @@ -17,7 +17,7 @@ note: ...so that reference does not outlive borrowed content | LL | self.foo(); | ^^^^ -note: but, the lifetime must be valid for the lifetime `'a` as defined on the trait at 4:11... +note: but, the lifetime must be valid for the lifetime 'a as defined on the trait at 4:11... --> $DIR/issue-17758.rs:4:11 | LL | trait Foo<'a> { @@ -28,4 +28,3 @@ LL | trait Foo<'a> { error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-17904-2.stderr b/src/test/ui/issues/issue-17904-2.stderr index 25f32b661031f..930409cc63727 100644 --- a/src/test/ui/issues/issue-17904-2.stderr +++ b/src/test/ui/issues/issue-17904-2.stderr @@ -4,7 +4,7 @@ error[E0392]: parameter `T` is never used LL | struct Foo where T: Copy; | ^ unused parameter | - = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `T` or using a marker such as `std::marker::PhantomData` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17905-2.stderr b/src/test/ui/issues/issue-17905-2.stderr index 04be62dc661bf..585bc9c14883b 100644 --- a/src/test/ui/issues/issue-17905-2.stderr +++ b/src/test/ui/issues/issue-17905-2.stderr @@ -15,7 +15,7 @@ LL | | LL | | println!("{:?}", self); LL | | } | |_____^ -note: ...does not necessarily outlive the lifetime `'_` as defined on the impl at 5:5 +note: ...does not necessarily outlive the lifetime '_ as defined on the impl at 5:5 --> $DIR/issue-17905-2.rs:5:5 | LL | &str, @@ -29,7 +29,7 @@ LL | fn say(self: &Pair<&str, isize>) { | = note: expected type `Pair<&str, _>` found type `Pair<&str, _>` -note: the lifetime `'_` as defined on the impl at 5:5... +note: the lifetime '_ as defined on the impl at 5:5... --> $DIR/issue-17905-2.rs:5:5 | LL | &str, diff --git a/src/test/ui/issues/issue-18119.stderr b/src/test/ui/issues/issue-18119.stderr index ddee5a9da7a42..4c5b940190ee6 100644 --- a/src/test/ui/issues/issue-18119.stderr +++ b/src/test/ui/issues/issue-18119.stderr @@ -18,4 +18,3 @@ LL | impl foo {} error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/issues/issue-19086.stderr b/src/test/ui/issues/issue-19086.stderr index e2229cbc20922..d2b9b90890e3c 100644 --- a/src/test/ui/issues/issue-19086.stderr +++ b/src/test/ui/issues/issue-19086.stderr @@ -1,9 +1,6 @@ error[E0532]: expected tuple struct/variant, found struct variant `FooB` --> $DIR/issue-19086.rs:10:9 | -LL | FooB { x: i32, y: i32 } - | ----------------------- `FooB` defined here -... LL | FooB(a, b) => println!("{} {}", a, b), | ^^^^ did you mean `FooB { /* fields */ }`? diff --git a/src/test/ui/issues/issue-19538.stderr b/src/test/ui/issues/issue-19538.stderr index 83c03b514ddcc..5415a45f7d621 100644 --- a/src/test/ui/issues/issue-19538.stderr +++ b/src/test/ui/issues/issue-19538.stderr @@ -17,7 +17,6 @@ LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^ the trait `Bar` cannot be made into an object | = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&mut dyn Bar>` for `&mut Thing` - = note: required by cast to type `&mut dyn Bar` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-19883.stderr b/src/test/ui/issues/issue-19883.stderr index e370b2ec1cb42..738add1684004 100644 --- a/src/test/ui/issues/issue-19883.stderr +++ b/src/test/ui/issues/issue-19883.stderr @@ -6,4 +6,3 @@ LL | >::Dst error: aborting due to previous error -For more information about this error, try `rustc --explain E0576`. diff --git a/src/test/ui/issues/issue-20005.stderr b/src/test/ui/issues/issue-20005.stderr index 31376f2d1be0f..2754d6bdd8306 100644 --- a/src/test/ui/issues/issue-20005.stderr +++ b/src/test/ui/issues/issue-20005.stderr @@ -7,13 +7,13 @@ LL | trait From { LL | / fn to( LL | | self LL | | ) -> >::Result where Dst: From { - | | - help: consider further restricting `Self`: `, Self: std::marker::Sized` LL | | From::from(self) LL | | } | |_____^ doesn't have a size known at compile-time | = 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 error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr index 6ecb4e736acd9..72a8fe4283b56 100644 --- a/src/test/ui/issues/issue-20413.stderr +++ b/src/test/ui/issues/issue-20413.stderr @@ -4,7 +4,7 @@ error[E0392]: parameter `T` is never used LL | struct NoData; | ^ unused parameter | - = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `T` or using a marker such as `std::marker::PhantomData` error[E0275]: overflow evaluating the requirement `NoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo` --> $DIR/issue-20413.rs:8:1 diff --git a/src/test/ui/issues/issue-20692.stderr b/src/test/ui/issues/issue-20692.stderr index 06c83f65be26c..66309394a426d 100644 --- a/src/test/ui/issues/issue-20692.stderr +++ b/src/test/ui/issues/issue-20692.stderr @@ -14,7 +14,6 @@ LL | let _ = x | = note: the trait cannot require that `Self : Sized` = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Array>` for `&T` - = note: required by cast to type `&dyn Array` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr index 13c9c09461eae..64e3cdc64c112 100644 --- a/src/test/ui/issues/issue-20831-debruijn.stderr +++ b/src/test/ui/issues/issue-20831-debruijn.stderr @@ -23,7 +23,7 @@ LL | | LL | | self.sub = t; LL | | } | |_____^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 26:6 +note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 26:6 --> $DIR/issue-20831-debruijn.rs:26:6 | LL | impl<'a> Publisher<'a> for MyStruct<'a> { @@ -43,7 +43,7 @@ LL | | } | = note: expected type `'a` found type `'_` -note: the lifetime `'a` as defined on the impl at 26:6... +note: the lifetime 'a as defined on the impl at 26:6... --> $DIR/issue-20831-debruijn.rs:26:6 | LL | impl<'a> Publisher<'a> for MyStruct<'a> { @@ -83,7 +83,7 @@ LL | | LL | | self.sub = t; LL | | } | |_____^ -note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6... +note: ...but the lifetime must also be valid for the lifetime 'a as defined on the impl at 26:6... --> $DIR/issue-20831-debruijn.rs:26:6 | LL | impl<'a> Publisher<'a> for MyStruct<'a> { @@ -94,5 +94,4 @@ LL | impl<'a> Publisher<'a> for MyStruct<'a> { error: aborting due to 3 previous errors -Some errors have detailed explanations: E0308, E0495. -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/issues/issue-21449.stderr b/src/test/ui/issues/issue-21449.stderr index ecaf6faba429e..21de1ea091568 100644 --- a/src/test/ui/issues/issue-21449.stderr +++ b/src/test/ui/issues/issue-21449.stderr @@ -6,4 +6,3 @@ LL | let myVar = MyMod { T: 0 }; error: aborting due to previous error -For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/issues/issue-21475.rs b/src/test/ui/issues/issue-21475.rs index ab0a18869632a..16d003aba7cab 100644 --- a/src/test/ui/issues/issue-21475.rs +++ b/src/test/ui/issues/issue-21475.rs @@ -1,5 +1,5 @@ // run-pass -#![allow(unused_imports, overlapping_patterns)] +#![allow(unused_imports)] // pretty-expanded FIXME #23616 use m::{START, END}; diff --git a/src/test/ui/never_type/issue-2149.rs b/src/test/ui/issues/issue-2149.rs similarity index 100% rename from src/test/ui/never_type/issue-2149.rs rename to src/test/ui/issues/issue-2149.rs diff --git a/src/test/ui/never_type/issue-2149.stderr b/src/test/ui/issues/issue-2149.stderr similarity index 100% rename from src/test/ui/never_type/issue-2149.stderr rename to src/test/ui/issues/issue-2149.stderr diff --git a/src/test/ui/issues/issue-21837.stderr b/src/test/ui/issues/issue-21837.stderr index 50fdf2d6185be..20d02a90315d0 100644 --- a/src/test/ui/issues/issue-21837.stderr +++ b/src/test/ui/issues/issue-21837.stderr @@ -5,9 +5,9 @@ LL | pub struct Foo(T); | ---------------------------- required by `Foo` ... LL | impl Trait2 for Foo {} - | - ^^^^^^ the trait `Bound` is not implemented for `T` - | | - | help: consider restricting this bound: `T: Bound` + | ^^^^^^ the trait `Bound` is not implemented for `T` + | + = help: consider adding a `where T: Bound` bound error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22037.stderr b/src/test/ui/issues/issue-22037.stderr index 615628558f08b..40d4a5e3bc0c5 100644 --- a/src/test/ui/issues/issue-22037.stderr +++ b/src/test/ui/issues/issue-22037.stderr @@ -6,4 +6,3 @@ LL | fn a(&self) -> ::X; error: aborting due to previous error -For more information about this error, try `rustc --explain E0576`. diff --git a/src/test/ui/issues/issue-22384.stderr b/src/test/ui/issues/issue-22384.stderr index 1f767a443d0f0..130c3124b6f82 100644 --- a/src/test/ui/issues/issue-22384.stderr +++ b/src/test/ui/issues/issue-22384.stderr @@ -6,4 +6,3 @@ LL | <::foobar as Trait>::foo(); error: aborting due to previous error -For more information about this error, try `rustc --explain E0576`. diff --git a/src/test/ui/issues/issue-22872.stderr b/src/test/ui/issues/issue-22872.stderr index 283a5e04a8b6f..fc5de23752b3e 100644 --- a/src/test/ui/issues/issue-22872.stderr +++ b/src/test/ui/issues/issue-22872.stderr @@ -1,12 +1,11 @@ error[E0277]: `

>::Item` is not an iterator --> $DIR/issue-22872.rs:20:40 | -LL | fn push_process

(process: P) where P: Process<'static> { - | - help: consider further restricting the associated type: `,

>::Item: std::iter::Iterator` LL | let _: Box Wrap<'b>> = Box::new(Wrapper(process)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `

>::Item` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `

>::Item` + = help: consider adding a `where

>::Item: std::iter::Iterator` bound = note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper

` = note: required for the cast to the object type `dyn for<'b> Wrap<'b>` diff --git a/src/test/ui/issues/issue-23189.stderr b/src/test/ui/issues/issue-23189.stderr index ed065212c560b..50c09f17486de 100644 --- a/src/test/ui/issues/issue-23189.stderr +++ b/src/test/ui/issues/issue-23189.stderr @@ -6,4 +6,3 @@ LL | let _ = module { x: 0 }; error: aborting due to previous error -For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/issues/issue-23302-1.stderr b/src/test/ui/issues/issue-23302-1.stderr index f2457774326dd..bbdb13a95007b 100644 --- a/src/test/ui/issues/issue-23302-1.stderr +++ b/src/test/ui/issues/issue-23302-1.stderr @@ -1,10 +1,10 @@ -error[E0391]: cycle detected when const checking `X::A::{{constant}}#0` +error[E0391]: cycle detected when processing `X::A::{{constant}}#0` --> $DIR/issue-23302-1.rs:4:9 | LL | A = X::A as isize, | ^^^^^^^^^^^^^ | - = note: ...which again requires const checking `X::A::{{constant}}#0`, completing the cycle + = note: ...which again requires processing `X::A::{{constant}}#0`, completing the cycle note: cycle used when processing `X::A::{{constant}}#0` --> $DIR/issue-23302-1.rs:4:9 | diff --git a/src/test/ui/issues/issue-23302-2.stderr b/src/test/ui/issues/issue-23302-2.stderr index c121c17b904ea..03afd82211a7e 100644 --- a/src/test/ui/issues/issue-23302-2.stderr +++ b/src/test/ui/issues/issue-23302-2.stderr @@ -1,10 +1,10 @@ -error[E0391]: cycle detected when const checking `Y::A::{{constant}}#0` +error[E0391]: cycle detected when processing `Y::A::{{constant}}#0` --> $DIR/issue-23302-2.rs:4:9 | LL | A = Y::B as isize, | ^^^^^^^^^^^^^ | - = note: ...which again requires const checking `Y::A::{{constant}}#0`, completing the cycle + = note: ...which again requires processing `Y::A::{{constant}}#0`, completing the cycle note: cycle used when processing `Y::A::{{constant}}#0` --> $DIR/issue-23302-2.rs:4:9 | diff --git a/src/test/ui/issues/issue-23302-3.stderr b/src/test/ui/issues/issue-23302-3.stderr index 0229469f04140..a7d643987f710 100644 --- a/src/test/ui/issues/issue-23302-3.stderr +++ b/src/test/ui/issues/issue-23302-3.stderr @@ -1,20 +1,26 @@ -error[E0391]: cycle detected when const checking `A` +error[E0391]: cycle detected when const checking if rvalue is promotable to static `A` + --> $DIR/issue-23302-3.rs:1:1 + | +LL | const A: i32 = B; + | ^^^^^^^^^^^^^^^^^ + | +note: ...which requires checking which parts of `A` are promotable to static... --> $DIR/issue-23302-3.rs:1:16 | LL | const A: i32 = B; | ^ +note: ...which requires const checking if rvalue is promotable to static `B`... + --> $DIR/issue-23302-3.rs:3:1 | -note: ...which requires const checking `B`... +LL | const B: i32 = A; + | ^^^^^^^^^^^^^^^^^ +note: ...which requires checking which parts of `B` are promotable to static... --> $DIR/issue-23302-3.rs:3:16 | LL | const B: i32 = A; | ^ - = note: ...which again requires const checking `A`, completing the cycle -note: cycle used when processing `A` - --> $DIR/issue-23302-3.rs:1:1 - | -LL | const A: i32 = B; - | ^^^^^^^^^^^^^^^^^ + = note: ...which again requires const checking if rvalue is promotable to static `A`, completing the cycle + = note: cycle used when running analysis passes on this crate error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23477.rs b/src/test/ui/issues/issue-23477.rs index 988ebe03ccf66..b10b2e49616fb 100644 --- a/src/test/ui/issues/issue-23477.rs +++ b/src/test/ui/issues/issue-23477.rs @@ -1,6 +1,5 @@ -// build-pass -// ignore-asmjs wasm2js does not support source maps yet -// compile-flags: -g +// build-pass (FIXME(62277): could be check-pass?) +// compiler-flags: -g pub struct Dst { pub a: (), diff --git a/src/test/ui/issues/issue-24687-embed-debuginfo/main.rs b/src/test/ui/issues/issue-24687-embed-debuginfo/main.rs index f08bcdfe6d16c..773792c7a3f1f 100644 --- a/src/test/ui/issues/issue-24687-embed-debuginfo/main.rs +++ b/src/test/ui/issues/issue-24687-embed-debuginfo/main.rs @@ -1,7 +1,6 @@ // run-pass // aux-build:issue-24687-lib.rs // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet extern crate issue_24687_lib as d; diff --git a/src/test/ui/issues/issue-24945-repeat-dash-opts.rs b/src/test/ui/issues/issue-24945-repeat-dash-opts.rs index 0f92fc2f7f31a..cf3834952c6a6 100644 --- a/src/test/ui/issues/issue-24945-repeat-dash-opts.rs +++ b/src/test/ui/issues/issue-24945-repeat-dash-opts.rs @@ -3,7 +3,6 @@ // as options to the compiler. // compile-flags:-g -g -O -O -// ignore-asmjs wasm2js does not support source maps yet fn main() { assert_eq!(1, 1); diff --git a/src/test/ui/issues/issue-26251.rs b/src/test/ui/issues/issue-26251.rs index edb06fea8ad53..0434ef9e5a958 100644 --- a/src/test/ui/issues/issue-26251.rs +++ b/src/test/ui/issues/issue-26251.rs @@ -1,6 +1,4 @@ // run-pass -#![allow(overlapping_patterns)] - fn main() { let x = 'a'; diff --git a/src/test/ui/issues/issue-26459.stderr b/src/test/ui/issues/issue-26459.stderr index 187369263a446..c7909a142bec4 100644 --- a/src/test/ui/issues/issue-26459.stderr +++ b/src/test/ui/issues/issue-26459.stderr @@ -6,4 +6,3 @@ LL | char{ch} => true error: aborting due to previous error -For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/issues/issue-26484.rs b/src/test/ui/issues/issue-26484.rs index 2a8750d3e431f..3b40b3dd8f075 100644 --- a/src/test/ui/issues/issue-26484.rs +++ b/src/test/ui/issues/issue-26484.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet fn helper bool>(_f: F) { print!(""); diff --git a/src/test/ui/issues/issue-27060-2.stderr b/src/test/ui/issues/issue-27060-2.stderr index 553041c5106c5..f7227c3410146 100644 --- a/src/test/ui/issues/issue-27060-2.stderr +++ b/src/test/ui/issues/issue-27060-2.stderr @@ -1,13 +1,12 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/issue-27060-2.rs:3:5 | -LL | pub struct Bad { - | -- help: consider further restricting this bound: `T: std::marker::Sized +` LL | data: T, | ^^^^^^^ 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: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run error: aborting due to previous error diff --git a/src/test/ui/issues/issue-27078.stderr b/src/test/ui/issues/issue-27078.stderr index fbc72d063f37c..76cc3e7b0a36e 100644 --- a/src/test/ui/issues/issue-27078.stderr +++ b/src/test/ui/issues/issue-27078.stderr @@ -2,12 +2,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation --> $DIR/issue-27078.rs:5:12 | LL | fn foo(self) -> &'static i32 { - | ^^^^ - help: consider further restricting `Self`: `where Self: std::marker::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 `Self` = note: to learn more, visit + = help: consider adding a `where Self: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature diff --git a/src/test/ui/issues/issue-27815.stderr b/src/test/ui/issues/issue-27815.stderr index 43f78ccf6395a..1d68e3bf558f3 100644 --- a/src/test/ui/issues/issue-27815.stderr +++ b/src/test/ui/issues/issue-27815.stderr @@ -24,4 +24,3 @@ LL | u32 { x: 1 } => {} error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/issues/issue-27942.stderr b/src/test/ui/issues/issue-27942.stderr index d290b176161be..e03959598b8b8 100644 --- a/src/test/ui/issues/issue-27942.stderr +++ b/src/test/ui/issues/issue-27942.stderr @@ -11,7 +11,7 @@ note: the anonymous lifetime #1 defined on the method body at 5:5... | LL | fn select(&self) -> BufferViewHandle; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the trait at 3:18 +note: ...does not necessarily outlive the lifetime 'a as defined on the trait at 3:18 --> $DIR/issue-27942.rs:3:18 | LL | pub trait Buffer<'a, R: Resources<'a>> { @@ -25,7 +25,7 @@ LL | fn select(&self) -> BufferViewHandle; | = note: expected type `Resources<'_>` found type `Resources<'a>` -note: the lifetime `'a` as defined on the trait at 3:18... +note: the lifetime 'a as defined on the trait at 3:18... --> $DIR/issue-27942.rs:3:18 | LL | pub trait Buffer<'a, R: Resources<'a>> { diff --git a/src/test/ui/issues/issue-28848.stderr b/src/test/ui/issues/issue-28848.stderr index 726844a31841f..5f0f202c0b27b 100644 --- a/src/test/ui/issues/issue-28848.stderr +++ b/src/test/ui/issues/issue-28848.stderr @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied LL | Foo::<'a, 'b>::xmute(u) | ^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'b` as defined on the function body at 9:16 +note: lifetime parameter instantiated with the lifetime 'b as defined on the function body at 9:16 --> $DIR/issue-28848.rs:9:16 | LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { | ^^ -note: but lifetime parameter must outlive the lifetime `'a` as defined on the function body at 9:12 +note: but lifetime parameter must outlive the lifetime 'a as defined on the function body at 9:12 --> $DIR/issue-28848.rs:9:12 | LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { diff --git a/src/test/ui/issues/issue-29948.rs b/src/test/ui/issues/issue-29948.rs index 5237a2f67bdd7..8ede8143ea657 100644 --- a/src/test/ui/issues/issue-29948.rs +++ b/src/test/ui/issues/issue-29948.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default use std::panic; diff --git a/src/test/ui/issues/issue-30535.stderr b/src/test/ui/issues/issue-30535.stderr index e3692934b62ad..5faf0374210d8 100644 --- a/src/test/ui/issues/issue-30535.stderr +++ b/src/test/ui/issues/issue-30535.stderr @@ -9,4 +9,3 @@ LL | _: foo::Foo::FooV error: aborting due to previous error -For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/issues/issue-31561.stderr b/src/test/ui/issues/issue-31561.stderr index d3c8e876b8a88..9ec26b024bce2 100644 --- a/src/test/ui/issues/issue-31561.stderr +++ b/src/test/ui/issues/issue-31561.stderr @@ -12,13 +12,6 @@ LL | | } ... LL | let Thing::Foo(y) = Thing::Foo(1); | ^^^^^^^^^^^^^ patterns `Bar` and `Baz` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let Thing::Foo(y) = Thing::Foo(1) { /* */ } - | error: aborting due to previous error diff --git a/src/test/ui/issues/issue-32004.stderr b/src/test/ui/issues/issue-32004.stderr index e9a5e217392a6..b56fa949acb7e 100644 --- a/src/test/ui/issues/issue-32004.stderr +++ b/src/test/ui/issues/issue-32004.stderr @@ -1,14 +1,11 @@ error[E0532]: expected unit struct/variant or constant, found tuple variant `Foo::Bar` --> $DIR/issue-32004.rs:10:9 | -LL | Bar(i32), - | -------- `Foo::Bar` defined here -... LL | Foo::Bar => {} | ^^^^^--- | | | | | help: a unit variant with a similar name exists: `Baz` - | did you mean `Foo::Bar( /* fields */ )`? + | 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-33096.rs b/src/test/ui/issues/issue-33096.rs index 2501e1430b3d1..f0b472e2fe821 100644 --- a/src/test/ui/issues/issue-33096.rs +++ b/src/test/ui/issues/issue-33096.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet use std::ops::Deref; diff --git a/src/test/ui/issues/issue-33992.rs b/src/test/ui/issues/issue-33992.rs index a6b137ba64594..94fccff9fc65d 100644 --- a/src/test/ui/issues/issue-33992.rs +++ b/src/test/ui/issues/issue-33992.rs @@ -1,7 +1,7 @@ // run-pass // ignore-windows // ignore-macos -// ignore-emscripten common linkage not implemented right now +// ignore-wasm32-bare common linkage not implemented right now #![feature(linkage)] diff --git a/src/test/ui/issues/issue-34569.rs b/src/test/ui/issues/issue-34569.rs index 88dcdd4113807..1f68560509e8c 100644 --- a/src/test/ui/issues/issue-34569.rs +++ b/src/test/ui/issues/issue-34569.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet // In this test we just want to make sure that the code below does not lead to // a debuginfo verification assertion during compilation. This was caused by the diff --git a/src/test/ui/issues/issue-35675.stderr b/src/test/ui/issues/issue-35675.stderr index 91814d9496376..28555a15afae1 100644 --- a/src/test/ui/issues/issue-35675.stderr +++ b/src/test/ui/issues/issue-35675.stderr @@ -63,9 +63,9 @@ LL | fn qux() -> Some { | ^^^^ | | | not a type - | help: try using the variant's enum: `std::option::Option` + | help: try using the variant's enum: `Option` error: aborting due to 7 previous errors -Some errors have detailed explanations: E0412, E0425, E0573. +Some errors have detailed explanations: E0412, E0425. For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/issues/issue-36163.stderr b/src/test/ui/issues/issue-36163.stderr index 3866243914b89..50e8cf6e88c58 100644 --- a/src/test/ui/issues/issue-36163.stderr +++ b/src/test/ui/issues/issue-36163.stderr @@ -1,15 +1,15 @@ -error[E0391]: cycle detected when const checking `Foo::B::{{constant}}#0` +error[E0391]: cycle detected when processing `Foo::B::{{constant}}#0` --> $DIR/issue-36163.rs:4:9 | LL | B = A, | ^ | -note: ...which requires const checking `A`... +note: ...which requires processing `A`... --> $DIR/issue-36163.rs:1:18 | LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^ - = note: ...which again requires const checking `Foo::B::{{constant}}#0`, completing the cycle + = note: ...which again requires processing `Foo::B::{{constant}}#0`, completing the cycle note: cycle used when processing `Foo::B::{{constant}}#0` --> $DIR/issue-36163.rs:4:9 | diff --git a/src/test/ui/issues/issue-36299.stderr b/src/test/ui/issues/issue-36299.stderr index a9516b8e5e51b..edbe790a0c9f6 100644 --- a/src/test/ui/issues/issue-36299.stderr +++ b/src/test/ui/issues/issue-36299.stderr @@ -4,7 +4,7 @@ error[E0392]: parameter `'a` is never used LL | struct Foo<'a, A> {} | ^^ unused parameter | - = help: consider removing `'a`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `'a` or using a marker such as `std::marker::PhantomData` error[E0392]: parameter `A` is never used --> $DIR/issue-36299.rs:1:16 @@ -12,7 +12,7 @@ error[E0392]: parameter `A` is never used LL | struct Foo<'a, A> {} | ^ unused parameter | - = help: consider removing `A`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `A` or using a marker such as `std::marker::PhantomData` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-36638.stderr b/src/test/ui/issues/issue-36638.stderr index fe48ea158de64..f3f94198465d8 100644 --- a/src/test/ui/issues/issue-36638.stderr +++ b/src/test/ui/issues/issue-36638.stderr @@ -16,7 +16,7 @@ error[E0392]: parameter `Self` is never used LL | struct Foo(Self); | ^^^^ unused parameter | - = help: consider removing `Self`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `Self` or using a marker such as `std::marker::PhantomData` error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-36856.rs b/src/test/ui/issues/issue-36856.rs index 5657ba69f9449..f2dfaf3dd367e 100644 --- a/src/test/ui/issues/issue-36856.rs +++ b/src/test/ui/issues/issue-36856.rs @@ -2,7 +2,6 @@ // Regression test for #36856. // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet fn g() -> bool { false diff --git a/src/test/ui/issues/issue-3707.stderr b/src/test/ui/issues/issue-3707.stderr index b98bc572a397c..05c8ce4c3f11e 100644 --- a/src/test/ui/issues/issue-3707.stderr +++ b/src/test/ui/issues/issue-3707.stderr @@ -5,7 +5,7 @@ LL | self.boom(); | -----^^^^ | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `Obj::boom` + | help: use associated function syntax instead: `&Obj::boom` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `Obj` diff --git a/src/test/ui/issues/issue-37534.stderr b/src/test/ui/issues/issue-37534.stderr index fadb9cdd1a3d1..3a0ab32dcc66b 100644 --- a/src/test/ui/issues/issue-37534.stderr +++ b/src/test/ui/issues/issue-37534.stderr @@ -8,7 +8,7 @@ help: possible better candidate is found in another module, you can import it in LL | use std::hash::Hash; | -warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default. Only `?Sized` is supported --> $DIR/issue-37534.rs:1:12 | LL | struct Foo { } @@ -20,7 +20,7 @@ error[E0392]: parameter `T` is never used LL | struct Foo { } | ^ unused parameter | - = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `T` or using a marker such as `std::marker::PhantomData` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-37884.stderr b/src/test/ui/issues/issue-37884.stderr index 8e75d7be066a3..9a5f659da1604 100644 --- a/src/test/ui/issues/issue-37884.stderr +++ b/src/test/ui/issues/issue-37884.stderr @@ -21,7 +21,7 @@ LL | | { LL | | Some(&mut self.0) LL | | } | |_____^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 3:6 +note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 3:6 --> $DIR/issue-37884.rs:3:6 | LL | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> { diff --git a/src/test/ui/issues/issue-38604.stderr b/src/test/ui/issues/issue-38604.stderr index 8b923a2c6b23f..8ef7d346cb331 100644 --- a/src/test/ui/issues/issue-38604.stderr +++ b/src/test/ui/issues/issue-38604.stderr @@ -14,7 +14,6 @@ LL | Box::new(()); | = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box<()>` - = note: required by cast to type `std::boxed::Box` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-38821.stderr b/src/test/ui/issues/issue-38821.stderr index 0687fc940dec1..dbd204ec299d7 100644 --- a/src/test/ui/issues/issue-38821.stderr +++ b/src/test/ui/issues/issue-38821.stderr @@ -4,6 +4,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat LL | #[derive(Debug, Copy, Clone)] | ^^^^ the trait `NotNull` is not implemented for `::SqlType` | + = help: consider adding a `where ::SqlType: NotNull` bound = note: required because of the requirements on the impl of `IntoNullable` for `::SqlType` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-39175.stderr b/src/test/ui/issues/issue-39175.stderr index 8b173e1b50c1e..66680b9936e68 100644 --- a/src/test/ui/issues/issue-39175.stderr +++ b/src/test/ui/issues/issue-39175.stderr @@ -5,7 +5,7 @@ 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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use std::os::unix::process::CommandExt; | diff --git a/src/test/ui/issues/issue-42210.rs b/src/test/ui/issues/issue-42210.rs index 01a5d563639b5..318e3099f98ba 100644 --- a/src/test/ui/issues/issue-42210.rs +++ b/src/test/ui/issues/issue-42210.rs @@ -2,7 +2,6 @@ // Regression test for #42210. // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet trait Foo { fn foo() { } diff --git a/src/test/ui/issues/issue-42312.stderr b/src/test/ui/issues/issue-42312.stderr index 6688203147eaf..bfdc4272fb308 100644 --- a/src/test/ui/issues/issue-42312.stderr +++ b/src/test/ui/issues/issue-42312.stderr @@ -2,12 +2,11 @@ error[E0277]: the size for values of type `::Target` ca --> $DIR/issue-42312.rs:4:29 | LL | fn baz(_: Self::Target) where Self: Deref {} - | ^ - help: consider further restricting the associated type: `, ::Target: std::marker::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 `::Target` = note: to learn more, visit + = help: consider adding a `where ::Target: std::marker::Sized` bound = note: all function arguments must have a statically known size = help: unsized locals are gated as an unstable feature diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr index 4dae6c1cd158e..33c3f18650a80 100644 --- a/src/test/ui/issues/issue-43189.stderr +++ b/src/test/ui/issues/issue-43189.stderr @@ -5,7 +5,7 @@ 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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use xcrate_issue_43189_b::xcrate_issue_43189_a::A; | diff --git a/src/test/ui/issues/issue-43784-associated-type.stderr b/src/test/ui/issues/issue-43784-associated-type.stderr index e91e53499ce6c..fc05d280693b8 100644 --- a/src/test/ui/issues/issue-43784-associated-type.stderr +++ b/src/test/ui/issues/issue-43784-associated-type.stderr @@ -2,9 +2,9 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/issue-43784-associated-type.rs:13:9 | LL | impl Complete for T { - | - ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::marker::Copy` + | ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | + = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/issues/issue-43784-supertrait.stderr b/src/test/ui/issues/issue-43784-supertrait.stderr index 5ac32041bce48..4c423f2e77fe8 100644 --- a/src/test/ui/issues/issue-43784-supertrait.stderr +++ b/src/test/ui/issues/issue-43784-supertrait.stderr @@ -2,9 +2,9 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/issue-43784-supertrait.rs:8:9 | LL | impl Complete for T {} - | - ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::marker::Copy` + | ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | + = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/issues/issue-43853.rs b/src/test/ui/issues/issue-43853.rs index 2a932db05af26..47c3ab59aa2eb 100644 --- a/src/test/ui/issues/issue-43853.rs +++ b/src/test/ui/issues/issue-43853.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default use std::panic; diff --git a/src/test/ui/never_type/issue-44402.rs b/src/test/ui/issues/issue-44402.rs similarity index 90% rename from src/test/ui/never_type/issue-44402.rs rename to src/test/ui/issues/issue-44402.rs index 699e480dfe7e5..29b7eb5ee49c7 100644 --- a/src/test/ui/never_type/issue-44402.rs +++ b/src/test/ui/issues/issue-44402.rs @@ -1,5 +1,4 @@ -// check-pass - +// build-pass (FIXME(62277): could be check-pass?) #![allow(dead_code)] #![feature(never_type)] #![feature(exhaustive_patterns)] diff --git a/src/test/ui/issues/issue-45731.rs b/src/test/ui/issues/issue-45731.rs index 5c5ac59873a3a..d20c07276a8c5 100644 --- a/src/test/ui/issues/issue-45731.rs +++ b/src/test/ui/issues/issue-45731.rs @@ -1,7 +1,6 @@ // run-pass #![allow(unused_variables)] // compile-flags:--test -g -// ignore-asmjs wasm2js does not support source maps yet #[cfg(target_os = "macos")] #[test] diff --git a/src/test/ui/issues/issue-46332.stderr b/src/test/ui/issues/issue-46332.stderr index c7e9d71700e6d..812a50000d1c2 100644 --- a/src/test/ui/issues/issue-46332.stderr +++ b/src/test/ui/issues/issue-46332.stderr @@ -2,7 +2,7 @@ error[E0422]: cannot find struct, variant or union type `TyUInt` in this scope --> $DIR/issue-46332.rs:9:5 | LL | TyUInt {}; - | ^^^^^^ help: a struct with a similar name exists (notice the capitalization): `TyUint` + | ^^^^^^ help: a struct with a similar name exists: `TyUint` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-46519.rs b/src/test/ui/issues/issue-46519.rs index 40c3117f01ce9..461ea2498b0d4 100644 --- a/src/test/ui/issues/issue-46519.rs +++ b/src/test/ui/issues/issue-46519.rs @@ -1,8 +1,6 @@ // run-pass // compile-flags:--test -O -// ignore-emscripten compiled with panic=abort by default - #[test] #[should_panic(expected = "creating inhabited type")] fn test() { diff --git a/src/test/ui/issues/issue-47486.rs b/src/test/ui/issues/issue-47486.rs deleted file mode 100644 index d686f02a9fe39..0000000000000 --- a/src/test/ui/issues/issue-47486.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - () < std::mem::size_of::<_>(); //~ ERROR: mismatched types - [0u8; std::mem::size_of::<_>()]; //~ ERROR: type annotations needed -} diff --git a/src/test/ui/issues/issue-47486.stderr b/src/test/ui/issues/issue-47486.stderr deleted file mode 100644 index af6e3010f7958..0000000000000 --- a/src/test/ui/issues/issue-47486.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/issue-47486.rs:2:10 - | -LL | () < std::mem::size_of::<_>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found usize - | - = note: expected type `()` - found type `usize` - -error[E0282]: type annotations needed - --> $DIR/issue-47486.rs:3:11 - | -LL | [0u8; std::mem::size_of::<_>()]; - | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0282, E0308. -For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/issues/issue-48508.rs b/src/test/ui/issues/issue-48508.rs index b7aa642287638..385192b882ba8 100644 --- a/src/test/ui/issues/issue-48508.rs +++ b/src/test/ui/issues/issue-48508.rs @@ -8,7 +8,6 @@ // compile-flags:-g // ignore-pretty issue #37195 -// ignore-asmjs wasm2js does not support source maps yet #![feature(non_ascii_idents)] diff --git a/src/test/ui/issues/issue-49579.rs b/src/test/ui/issues/issue-49579.rs index 767e06c4e90c5..79cc107d4fec2 100644 --- a/src/test/ui/issues/issue-49579.rs +++ b/src/test/ui/issues/issue-49579.rs @@ -1,4 +1,5 @@ // build-pass (FIXME(62277): could be check-pass?) +// ignore-emscripten no i128 support fn fibs(n: u32) -> impl Iterator { (0 .. n) diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs index 24c61425b8e29..67feb3ff6aec3 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs @@ -1,3 +1,5 @@ +#![feature(inner_deref)] + fn main() { let _result = &Some(42).as_deref(); //~^ ERROR no method named `as_deref` found for type `std::option::Option<{integer}>` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index 0eb7bf0247565..345f91437b827 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `as_deref` found for type `std::option::Option<{integer}>` in the current scope - --> $DIR/option-as_deref.rs:2:29 + --> $DIR/option-as_deref.rs:4:29 | LL | let _result = &Some(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs index 67ad73f584773..56aead8d0e00d 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs @@ -1,3 +1,5 @@ +#![feature(inner_deref)] + fn main() { let _result = &mut Some(42).as_deref_mut(); //~^ ERROR no method named `as_deref_mut` found for type `std::option::Option<{integer}>` 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 845ddb52319c7..29fd15fb396e9 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 @@ -1,5 +1,5 @@ error[E0599]: no method named `as_deref_mut` found for type `std::option::Option<{integer}>` in the current scope - --> $DIR/option-as_deref_mut.rs:2:33 + --> $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}>` diff --git a/src/test/ui/issues/issue-50571.rs b/src/test/ui/issues/issue-50571.rs deleted file mode 100644 index 728c113bdc323..0000000000000 --- a/src/test/ui/issues/issue-50571.rs +++ /dev/null @@ -1,6 +0,0 @@ -trait Foo { - fn foo([a, b]: [i32; 2]) {} - //~^ ERROR: patterns aren't allowed in methods without bodies -} - -fn main() {} diff --git a/src/test/ui/issues/issue-50571.stderr b/src/test/ui/issues/issue-50571.stderr deleted file mode 100644 index 834635388a066..0000000000000 --- a/src/test/ui/issues/issue-50571.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0642]: patterns aren't allowed in methods without bodies - --> $DIR/issue-50571.rs:2:12 - | -LL | fn foo([a, b]: [i32; 2]) {} - | ^^^^^^ -help: give this argument a name or use an underscore to ignore it - | -LL | fn foo(_: [i32; 2]) {} - | ^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0642`. diff --git a/src/test/ui/issues/issue-52213.stderr b/src/test/ui/issues/issue-52213.stderr index b79a5ddf3e1bf..b4df10efc5d8d 100644 --- a/src/test/ui/issues/issue-52213.stderr +++ b/src/test/ui/issues/issue-52213.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | match (&t,) { | ^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 1:23... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 1:23... --> $DIR/issue-52213.rs:1:23 | LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { @@ -12,7 +12,7 @@ LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { = note: ...so that the types are compatible: expected (&&(T,),) found (&&'a (T,),) -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 1:27... +note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 1:27... --> $DIR/issue-52213.rs:1:27 | LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { @@ -25,4 +25,3 @@ LL | ((u,),) => u, error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-52262.rs b/src/test/ui/issues/issue-52262.rs deleted file mode 100644 index 2195b89555791..0000000000000 --- a/src/test/ui/issues/issue-52262.rs +++ /dev/null @@ -1,25 +0,0 @@ -// compile-flags:-Ztreat-err-as-bug=5 -#[derive(Debug)] -enum MyError { - NotFound { key: Vec }, - Err41, -} - -impl std::error::Error for MyError {} - -impl std::fmt::Display for MyError { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match self { - MyError::NotFound { key } => write!( - f, - "unknown error with code {}.", - String::from_utf8(*key).unwrap() - //~^ ERROR cannot move out of `*key` which is behind a shared reference - ), - MyError::Err41 => write!(f, "Sit by a lake"), - } - } -} -fn main() { - println!("Hello, world!"); -} diff --git a/src/test/ui/issues/issue-52262.stderr b/src/test/ui/issues/issue-52262.stderr deleted file mode 100644 index 7312976c80159..0000000000000 --- a/src/test/ui/issues/issue-52262.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0507]: cannot move out of `*key` which is behind a shared reference - --> $DIR/issue-52262.rs:16:35 - | -LL | String::from_utf8(*key).unwrap() - | ^^^^ move occurs because `*key` has type `std::vec::Vec`, which does not implement the `Copy` trait - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/issues/issue-54348.rs b/src/test/ui/issues/issue-54348.rs index e7221e2cbb1e1..68d838054776e 100644 --- a/src/test/ui/issues/issue-54348.rs +++ b/src/test/ui/issues/issue-54348.rs @@ -1,7 +1,5 @@ fn main() { [1][0u64 as usize]; [1][1.5 as usize]; //~ ERROR index out of bounds - //~| ERROR this expression will panic at runtime [1][1u64 as usize]; //~ ERROR index out of bounds - //~| ERROR this expression will panic at runtime } diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr index 79320ef4f31c7..fa77bd6fd7797 100644 --- a/src/test/ui/issues/issue-54348.stderr +++ b/src/test/ui/issues/issue-54348.stderr @@ -6,23 +6,11 @@ LL | [1][1.5 as usize]; | = note: `#[deny(const_err)]` on by default -error: this expression will panic at runtime - --> $DIR/issue-54348.rs:3:5 - | -LL | [1][1.5 as usize]; - | ^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 - error: index out of bounds: the len is 1 but the index is 1 - --> $DIR/issue-54348.rs:5:5 + --> $DIR/issue-54348.rs:4:5 | LL | [1][1u64 as usize]; | ^^^^^^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-54348.rs:5:5 - | -LL | [1][1u64 as usize]; - | ^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr index 7b910f5e3e5a6..9e67e5e125f62 100644 --- a/src/test/ui/issues/issue-55796.stderr +++ b/src/test/ui/issues/issue-55796.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | Box::new(self.out_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the trait at 5:17... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 5:17... --> $DIR/issue-55796.rs:5:17 | LL | pub trait Graph<'a> { @@ -25,7 +25,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | Box::new(self.in_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the trait at 5:17... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 5:17... --> $DIR/issue-55796.rs:5:17 | LL | pub trait Graph<'a> { @@ -42,4 +42,3 @@ LL | Box::new(self.in_edges(u).map(|e| e.target())) error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-57271.rs b/src/test/ui/issues/issue-57271.rs deleted file mode 100644 index 9940fecbeed53..0000000000000 --- a/src/test/ui/issues/issue-57271.rs +++ /dev/null @@ -1,24 +0,0 @@ -// aux-build:issue-57271-lib.rs - -extern crate issue_57271_lib; - -use issue_57271_lib::BaseType; - -pub enum ObjectType { //~ ERROR recursive type `ObjectType` has infinite size - Class(ClassTypeSignature), - Array(TypeSignature), - TypeVariable(()), -} - -pub struct ClassTypeSignature { - pub package: (), - pub class: (), - pub inner: (), -} - -pub enum TypeSignature { //~ ERROR recursive type `TypeSignature` has infinite size - Base(BaseType), - Object(ObjectType), -} - -fn main() {} diff --git a/src/test/ui/issues/issue-57271.stderr b/src/test/ui/issues/issue-57271.stderr deleted file mode 100644 index 4f164624f7a53..0000000000000 --- a/src/test/ui/issues/issue-57271.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0072]: recursive type `ObjectType` has infinite size - --> $DIR/issue-57271.rs:7:1 - | -LL | pub enum ObjectType { - | ^^^^^^^^^^^^^^^^^^^ recursive type has infinite size -LL | Class(ClassTypeSignature), -LL | Array(TypeSignature), - | ------------- recursive without indirection - | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ObjectType` representable - -error[E0072]: recursive type `TypeSignature` has infinite size - --> $DIR/issue-57271.rs:19:1 - | -LL | pub enum TypeSignature { - | ^^^^^^^^^^^^^^^^^^^^^^ recursive type has infinite size -LL | Base(BaseType), -LL | Object(ObjectType), - | ---------- recursive without indirection - | - = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `TypeSignature` representable - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/issues/issue-57399-self-return-impl-trait.rs b/src/test/ui/issues/issue-57399-self-return-impl-trait.rs deleted file mode 100644 index 23d68263b3a27..0000000000000 --- a/src/test/ui/issues/issue-57399-self-return-impl-trait.rs +++ /dev/null @@ -1,22 +0,0 @@ -// run-pass - -trait T { - type T; -} - -impl T for i32 { - type T = u32; -} - -struct S { - a: A, -} - - -impl From for S<::T> { - fn from(a: u32) -> Self { - Self { a } - } -} - -fn main() {} diff --git a/src/test/ui/issues/issue-57399-self-return-impl-trait.stderr b/src/test/ui/issues/issue-57399-self-return-impl-trait.stderr deleted file mode 100644 index 5c71410a8275c..0000000000000 --- a/src/test/ui/issues/issue-57399-self-return-impl-trait.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: field is never used: `a` - --> $DIR/issue-57399-self-return-impl-trait.rs:12:5 - | -LL | a: A, - | ^^^^ - | - = note: `#[warn(dead_code)]` on by default - diff --git a/src/test/ui/issues/issue-58022.rs b/src/test/ui/issues/issue-58022.rs deleted file mode 100644 index c6dd45e6cf3e9..0000000000000 --- a/src/test/ui/issues/issue-58022.rs +++ /dev/null @@ -1,18 +0,0 @@ -pub trait Foo: Sized { - const SIZE: usize; - - fn new(slice: &[u8; Foo::SIZE]) -> Self; - //~^ ERROR: type annotations needed: cannot resolve `_: Foo` -} - -pub struct Bar(T); - -impl Bar<[u8]> { - const SIZE: usize = 32; - - fn new(slice: &[u8; Self::SIZE]) -> Self { - Foo(Box::new(*slice)) //~ ERROR: expected function, found trait `Foo` - } -} - -fn main() {} diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr deleted file mode 100644 index 71bad7b81fa87..0000000000000 --- a/src/test/ui/issues/issue-58022.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0423]: expected function, found trait `Foo` - --> $DIR/issue-58022.rs:14:9 - | -LL | Foo(Box::new(*slice)) - | ^^^ not a function - -error[E0283]: type annotations needed: cannot resolve `_: Foo` - --> $DIR/issue-58022.rs:4:25 - | -LL | const SIZE: usize; - | ------------------ required by `Foo::SIZE` -LL | -LL | fn new(slice: &[u8; Foo::SIZE]) -> Self; - | ^^^^^^^^^ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0283, E0423. -For more information about an error, try `rustc --explain E0283`. diff --git a/src/test/ui/issues/issue-58344.rs b/src/test/ui/issues/issue-58344.rs deleted file mode 100644 index 99b656d74f505..0000000000000 --- a/src/test/ui/issues/issue-58344.rs +++ /dev/null @@ -1,50 +0,0 @@ -use std::ops::Add; - -trait Trait { - fn get(self) -> T; -} - -struct Holder(T); - -impl Trait for Holder { - fn get(self) -> T { - self.0 - } -} - -enum Either { - Left(L), - Right(R), -} - -impl Either { - fn converge(self) -> T where L: Trait, R: Trait { - match self { - Either::Left(val) => val.get(), - Either::Right(val) => val.get(), - } - } -} - -fn add_generic, B>(lhs: A, rhs: B) -> Either< - impl Trait<>::Output>, - impl Trait<>::Output> -> { - if true { - Either::Left(Holder(lhs + rhs)) - } else { - Either::Right(Holder(lhs + rhs)) - } -} - -fn add_one( - value: u32, -) -> Either>::Output>, impl Trait<>::Output>> { - //~^ ERROR: the trait bound `impl Trait<::Output>: Trait` - //~| ERROR: the trait bound `impl Trait<::Output>: Trait` - add_generic(value, 1u32) -} - -pub fn main() { - add_one(3).converge(); -} diff --git a/src/test/ui/issues/issue-58344.stderr b/src/test/ui/issues/issue-58344.stderr deleted file mode 100644 index 427d03b679d5f..0000000000000 --- a/src/test/ui/issues/issue-58344.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0277]: the trait bound `impl Trait<::Output>: Trait` is not satisfied - --> $DIR/issue-58344.rs:42:13 - | -LL | ) -> Either>::Output>, impl Trait<>::Output>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `impl Trait<::Output>` - | - = note: the return type of a function must have a statically known size - -error[E0277]: the trait bound `impl Trait<::Output>: Trait` is not satisfied - --> $DIR/issue-58344.rs:42:52 - | -LL | ) -> Either>::Output>, impl Trait<>::Output>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `impl Trait<::Output>` - | - = note: the return type of a function must have a statically known size - -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-58463.rs b/src/test/ui/issues/issue-58463.rs index af93f76221d4e..8ab845366b7b4 100644 --- a/src/test/ui/issues/issue-58463.rs +++ b/src/test/ui/issues/issue-58463.rs @@ -1,7 +1,5 @@ // run-pass // compile-flags:-C debuginfo=2 -// ignore-asmjs wasm2js does not support source maps yet - fn foo() -> impl Copy { foo } diff --git a/src/test/ui/issues/issue-60218.rs b/src/test/ui/issues/issue-60218.rs deleted file mode 100644 index 4926691f3b568..0000000000000 --- a/src/test/ui/issues/issue-60218.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Regression test for #60218 -// -// This was reported to cause ICEs. - -use std::iter::Map; - -pub trait Foo {} - -pub fn trigger_error(iterable: I, functor: F) -where - for<'t> &'t I: IntoIterator, -for<'t> Map<<&'t I as IntoIterator>::IntoIter, F>: Iterator, -for<'t> ::IntoIter, F> as Iterator>::Item: Foo, -{ -} - -fn main() { - trigger_error(vec![], |x: &u32| x) //~ ERROR E0277 -} diff --git a/src/test/ui/issues/issue-60218.stderr b/src/test/ui/issues/issue-60218.stderr deleted file mode 100644 index a9970cc109699..0000000000000 --- a/src/test/ui/issues/issue-60218.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0277]: the trait bound `for<'t> ::IntoIter, _> as std::iter::Iterator>::Item: Foo` is not satisfied - --> $DIR/issue-60218.rs:18:5 - | -LL | pub fn trigger_error(iterable: I, functor: F) - | ------------- -... -LL | for<'t> ::IntoIter, F> as Iterator>::Item: Foo, - | --- required by this bound in `trigger_error` -... -LL | trigger_error(vec![], |x: &u32| x) - | ^^^^^^^^^^^^^ the trait `for<'t> Foo` is not implemented for `::IntoIter, _> as std::iter::Iterator>::Item` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-63983.stderr b/src/test/ui/issues/issue-63983.stderr index 8949c475b6f72..67acd1d57c27a 100644 --- a/src/test/ui/issues/issue-63983.stderr +++ b/src/test/ui/issues/issue-63983.stderr @@ -1,18 +1,12 @@ error[E0532]: expected unit struct/variant or constant, found tuple variant `MyEnum::Tuple` --> $DIR/issue-63983.rs:8:9 | -LL | Tuple(i32), - | ---------- `MyEnum::Tuple` defined here -... LL | MyEnum::Tuple => "", - | ^^^^^^^^^^^^^ did you mean `MyEnum::Tuple( /* fields */ )`? + | ^^^^^^^^^^^^^ 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 | Struct{ s: i32 }, - | ---------------- `MyEnum::Struct` defined here -... LL | MyEnum::Struct => "", | ^^^^^^^^^^^^^^ did you mean `MyEnum::Struct { /* fields */ }`? diff --git a/src/test/ui/issues/issue-64620.rs b/src/test/ui/issues/issue-64620.rs deleted file mode 100644 index a62e5bf8d3c62..0000000000000 --- a/src/test/ui/issues/issue-64620.rs +++ /dev/null @@ -1,5 +0,0 @@ -enum Bug { - V1 = return [0][0] //~ERROR return statement outside of function body -} - -fn main() {} diff --git a/src/test/ui/issues/issue-64620.stderr b/src/test/ui/issues/issue-64620.stderr deleted file mode 100644 index f40ac4de32d59..0000000000000 --- a/src/test/ui/issues/issue-64620.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0572]: return statement outside of function body - --> $DIR/issue-64620.rs:2:10 - | -LL | V1 = return [0][0] - | ^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0572`. diff --git a/src/test/ui/issues/issue-64792-bad-unicode-ctor.rs b/src/test/ui/issues/issue-64792-bad-unicode-ctor.rs deleted file mode 100644 index 7bce57923a5b7..0000000000000 --- a/src/test/ui/issues/issue-64792-bad-unicode-ctor.rs +++ /dev/null @@ -1,5 +0,0 @@ -struct X {} - -const Y: X = X("ö"); //~ ERROR expected function, found struct `X` - -fn main() {} diff --git a/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr b/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr deleted file mode 100644 index ae9025bb041ab..0000000000000 --- a/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0423]: expected function, found struct `X` - --> $DIR/issue-64792-bad-unicode-ctor.rs:3:14 - | -LL | struct X {} - | ----------- `X` defined here -LL | -LL | const Y: X = X("ö"); - | ^ - | | - | did you mean `X { /* fields */ }`? - | help: a constant with a similar name exists: `Y` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs deleted file mode 100644 index e0eaafdfc2f22..0000000000000 --- a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs +++ /dev/null @@ -1,11 +0,0 @@ -trait Foo { - fn foo(&self); -} - -trait Bar {} - -fn do_stuff(t : T) { - t.foo() //~ ERROR no method named `foo` found for type `T` in the current scope -} - -fn main() {} diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr deleted file mode 100644 index 24bf60abf6a78..0000000000000 --- a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0599]: no method named `foo` found for type `T` in the current scope - --> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7 - | -LL | t.foo() - | ^^^ 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 `foo`, perhaps you need to restrict type parameter `T` with it: - | -LL | fn do_stuff(t : T) { - | ^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-65611.rs b/src/test/ui/issues/issue-65611.rs deleted file mode 100644 index b74ee1b0c6e54..0000000000000 --- a/src/test/ui/issues/issue-65611.rs +++ /dev/null @@ -1,63 +0,0 @@ -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 deleted file mode 100644 index cb441c13c6b9e..0000000000000 --- a/src/test/ui/issues/issue-65611.stderr +++ /dev/null @@ -1,18 +0,0 @@ -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/iterators/iter-count-overflow-debug.rs b/src/test/ui/iterators/iter-count-overflow-debug.rs index fdd285dcad2a1..d661203575083 100644 --- a/src/test/ui/iterators/iter-count-overflow-debug.rs +++ b/src/test/ui/iterators/iter-count-overflow-debug.rs @@ -1,6 +1,6 @@ // run-pass // only-32bit too impatient for 2⁶⁴ items -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes -C opt-level=3 use std::panic; diff --git a/src/test/ui/iterators/iter-position-overflow-debug.rs b/src/test/ui/iterators/iter-position-overflow-debug.rs index b578999af8e94..f1eded31702c4 100644 --- a/src/test/ui/iterators/iter-position-overflow-debug.rs +++ b/src/test/ui/iterators/iter-position-overflow-debug.rs @@ -1,6 +1,6 @@ // run-pass // only-32bit too impatient for 2⁶⁴ items -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes -C opt-level=3 use std::panic; diff --git a/src/test/ui/iterators/iter-step-overflow-debug.rs b/src/test/ui/iterators/iter-step-overflow-debug.rs index 3872a03b68259..5d67c7cbb4256 100644 --- a/src/test/ui/iterators/iter-step-overflow-debug.rs +++ b/src/test/ui/iterators/iter-step-overflow-debug.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes use std::panic; diff --git a/src/test/ui/iterators/iter-sum-overflow-debug.rs b/src/test/ui/iterators/iter-sum-overflow-debug.rs index 4a9e8cdb72e70..ee4ab4d24c6ab 100644 --- a/src/test/ui/iterators/iter-sum-overflow-debug.rs +++ b/src/test/ui/iterators/iter-sum-overflow-debug.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes use std::panic; diff --git a/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs b/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs index 6bd1425e32465..429f8e0bc9648 100644 --- a/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs +++ b/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C overflow-checks use std::panic; diff --git a/src/test/ui/json-bom-plus-crlf-multifile-aux.rs b/src/test/ui/json-bom-plus-crlf-multifile-aux.rs deleted file mode 100644 index 991ea1d85d2ca..0000000000000 --- a/src/test/ui/json-bom-plus-crlf-multifile-aux.rs +++ /dev/null @@ -1,27 +0,0 @@ -// (This line has BOM so it's ignored by compiletest for directives) -// -// ignore-test Not a test. Used by other tests -// ignore-tidy-cr - -// For easier verifying, the byte offsets in this file should match those -// in the json-bom-plus-crlf.rs - given the actual fn is identical (just with -// a different, but equally sized name), the easiest way to do this is to -// ensure the two files are of equal size on disk. -// Padding............................ - -// N.B., this file needs CRLF line endings. The .gitattributes file in -// this directory should enforce it. - -pub fn test() { - - let s : String = 1; // Error in the middle of line. - - let s : String = 1 - ; // Error before the newline. - - let s : String = -1; // Error after the newline. - - let s : String = ( - ); // Error spanning the newline. -} diff --git a/src/test/ui/json-bom-plus-crlf-multifile.rs b/src/test/ui/json-bom-plus-crlf-multifile.rs deleted file mode 100644 index c71dd325f4427..0000000000000 --- a/src/test/ui/json-bom-plus-crlf-multifile.rs +++ /dev/null @@ -1,12 +0,0 @@ -// (This line has BOM so it's ignored by compiletest for directives) -// -// build-fail -// compile-flags: --json=diagnostic-short --error-format=json -// ignore-tidy-cr - -#[path = "json-bom-plus-crlf-multifile-aux.rs"] -mod json_bom_plus_crlf_multifile_aux; - -fn main() { - json_bom_plus_crlf_multifile_aux::test(); -} diff --git a/src/test/ui/json-bom-plus-crlf-multifile.stderr b/src/test/ui/json-bom-plus-crlf-multifile.stderr deleted file mode 100644 index 8472f16108909..0000000000000 --- a/src/test/ui/json-bom-plus-crlf-multifile.stderr +++ /dev/null @@ -1,86 +0,0 @@ -{"message":"mismatched types","code":{"code":"E0308","explanation":" -This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. - -For example: - -```compile_fail,E0308 -let x: i32 = \"I am not a number!\"; -// ~~~ ~~~~~~~~~~~~~~~~~~~~ -// | | -// | initializing expression; -// | compiler infers type `&str` -// | -// type `i32` assigned to variable `x` -``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected type `std::string::String` - found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":" -This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. - -For example: - -```compile_fail,E0308 -let x: i32 = \"I am not a number!\"; -// ~~~ ~~~~~~~~~~~~~~~~~~~~ -// | | -// | initializing expression; -// | compiler infers type `&str` -// | -// type `i32` assigned to variable `x` -``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected type `std::string::String` - found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":" -This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. - -For example: - -```compile_fail,E0308 -let x: i32 = \"I am not a number!\"; -// ~~~ ~~~~~~~~~~~~~~~~~~~~ -// | | -// | initializing expression; -// | compiler infers type `&str` -// | -// type `i32` assigned to variable `x` -``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected type `std::string::String` - found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":" -This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. - -For example: - -```compile_fail,E0308 -let x: i32 = \"I am not a number!\"; -// ~~~ ~~~~~~~~~~~~~~~~~~~~ -// | | -// | initializing expression; -// | compiler infers type `&str` -// | -// type `i32` assigned to variable `x` -``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found ()","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected type `std::string::String` - found type `()`","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types -"} -{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors -"} diff --git a/src/test/ui/json-bom-plus-crlf.rs b/src/test/ui/json-bom-plus-crlf.rs deleted file mode 100644 index ae54a35d4805c..0000000000000 --- a/src/test/ui/json-bom-plus-crlf.rs +++ /dev/null @@ -1,27 +0,0 @@ -// (This line has BOM so it's ignored by compiletest for directives) -// -// build-fail -// compile-flags: --json=diagnostic-short --error-format=json -// ignore-tidy-cr - -// For easier verifying, the byte offsets in this file should match those -// in the json_bom_plus_crlf_multifile_aux.rs - given the actual fn is -// identical (just with a different, but equally sized name), the easiest way -// to do this is to ensure the two files are of equal size on disk. - -// N.B., this file needs CRLF line endings. The .gitattributes file in -// this directory should enforce it. - -fn main() { - - let s : String = 1; // Error in the middle of line. - - let s : String = 1 - ; // Error before the newline. - - let s : String = -1; // Error after the newline. - - let s : String = ( - ); // Error spanning the newline. -} diff --git a/src/test/ui/json-bom-plus-crlf.stderr b/src/test/ui/json-bom-plus-crlf.stderr deleted file mode 100644 index 17775f59fd16f..0000000000000 --- a/src/test/ui/json-bom-plus-crlf.stderr +++ /dev/null @@ -1,86 +0,0 @@ -{"message":"mismatched types","code":{"code":"E0308","explanation":" -This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. - -For example: - -```compile_fail,E0308 -let x: i32 = \"I am not a number!\"; -// ~~~ ~~~~~~~~~~~~~~~~~~~~ -// | | -// | initializing expression; -// | compiler infers type `&str` -// | -// type `i32` assigned to variable `x` -``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected type `std::string::String` - found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:17:22: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":" -This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. - -For example: - -```compile_fail,E0308 -let x: i32 = \"I am not a number!\"; -// ~~~ ~~~~~~~~~~~~~~~~~~~~ -// | | -// | initializing expression; -// | compiler infers type `&str` -// | -// type `i32` assigned to variable `x` -``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected type `std::string::String` - found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:19:22: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":" -This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. - -For example: - -```compile_fail,E0308 -let x: i32 = \"I am not a number!\"; -// ~~~ ~~~~~~~~~~~~~~~~~~~~ -// | | -// | initializing expression; -// | compiler infers type `&str` -// | -// type `i32` assigned to variable `x` -``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected type `std::string::String` - found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:23:1: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":" -This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. - -For example: - -```compile_fail,E0308 -let x: i32 = \"I am not a number!\"; -// ~~~ ~~~~~~~~~~~~~~~~~~~~ -// | | -// | initializing expression; -// | compiler infers type `&str` -// | -// type `i32` assigned to variable `x` -``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found ()","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected type `std::string::String` - found type `()`","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:25:22: error[E0308]: mismatched types -"} -{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors -"} diff --git a/src/test/ui/kindck/kindck-impl-type-params.nll.stderr b/src/test/ui/kindck/kindck-impl-type-params.nll.stderr index 82efa83990553..25d0e74187f75 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.nll.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params.nll.stderr @@ -1,50 +1,42 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/kindck-impl-type-params.rs:18:13 | -LL | fn f(val: T) { - | - help: consider restricting this bound: `T: std::marker::Send` -LL | let t: S = S(marker::PhantomData); LL | let a = &t as &dyn Gettable; | ^^ `T` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `T` + = help: consider adding a `where T: std::marker::Send` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:18:13 | -LL | fn f(val: T) { - | - help: consider restricting this bound: `T: std::marker::Copy` -LL | let t: S = S(marker::PhantomData); LL | let a = &t as &dyn Gettable; | ^^ the trait `std::marker::Copy` is not implemented for `T` | + = help: consider adding a `where T: std::marker::Copy` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` error[E0277]: `T` cannot be sent between threads safely --> $DIR/kindck-impl-type-params.rs:25:31 | -LL | fn g(val: T) { - | - help: consider restricting this bound: `T: std::marker::Send` -LL | let t: S = S(marker::PhantomData); LL | let a: &dyn Gettable = &t; | ^^ `T` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `T` + = help: consider adding a `where T: std::marker::Send` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:25:31 | -LL | fn g(val: T) { - | - help: consider restricting this bound: `T: std::marker::Copy` -LL | let t: S = S(marker::PhantomData); LL | let a: &dyn Gettable = &t; | ^^ the trait `std::marker::Copy` is not implemented for `T` | + = help: consider adding a `where T: std::marker::Copy` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` diff --git a/src/test/ui/kindck/kindck-impl-type-params.stderr b/src/test/ui/kindck/kindck-impl-type-params.stderr index 777a553c2a58a..e6f7088bd4635 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params.stderr @@ -1,50 +1,42 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/kindck-impl-type-params.rs:18:13 | -LL | fn f(val: T) { - | - help: consider restricting this bound: `T: std::marker::Send` -LL | let t: S = S(marker::PhantomData); LL | let a = &t as &dyn Gettable; | ^^ `T` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `T` + = help: consider adding a `where T: std::marker::Send` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:18:13 | -LL | fn f(val: T) { - | - help: consider restricting this bound: `T: std::marker::Copy` -LL | let t: S = S(marker::PhantomData); LL | let a = &t as &dyn Gettable; | ^^ the trait `std::marker::Copy` is not implemented for `T` | + = help: consider adding a `where T: std::marker::Copy` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` error[E0277]: `T` cannot be sent between threads safely --> $DIR/kindck-impl-type-params.rs:25:31 | -LL | fn g(val: T) { - | - help: consider restricting this bound: `T: std::marker::Send` -LL | let t: S = S(marker::PhantomData); LL | let a: &dyn Gettable = &t; | ^^ `T` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `T` + = help: consider adding a `where T: std::marker::Send` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:25:31 | -LL | fn g(val: T) { - | - help: consider restricting this bound: `T: std::marker::Copy` -LL | let t: S = S(marker::PhantomData); LL | let a: &dyn Gettable = &t; | ^^ the trait `std::marker::Copy` is not implemented for `T` | + = help: consider adding a `where T: std::marker::Copy` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr deleted file mode 100644 index 7c67c5f9e9596..0000000000000 --- a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied - --> $DIR/kindck-inherited-copy-bound.rs:21: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}>` - | - = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>` - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/kindck-inherited-copy-bound.rs:28:13 - | -LL | let z = &x as &dyn Foo; - | ^^ the trait `Foo` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box` - = note: required by cast to type `&dyn Foo` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0038, E0277. -For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.rs b/src/test/ui/kindck/kindck-inherited-copy-bound.rs index aad693e5b1937..61e72908248df 100644 --- a/src/test/ui/kindck/kindck-inherited-copy-bound.rs +++ b/src/test/ui/kindck/kindck-inherited-copy-bound.rs @@ -1,8 +1,5 @@ // Test that Copy bounds inherited by trait are checked. -// -// revisions: curr object_safe_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] #![feature(box_syntax)] use std::any::Any; @@ -18,17 +15,15 @@ fn take_param(foo: &T) { } fn a() { let x: Box<_> = box 3; - take_param(&x); //[curr]~ ERROR E0277 - //[object_safe_for_dispatch]~^ ERROR E0277 + take_param(&x); //~ ERROR E0277 } fn b() { let x: Box<_> = box 3; let y = &x; let z = &x as &dyn Foo; - //[curr]~^ ERROR E0038 - //[curr]~| ERROR E0038 - //[object_safe_for_dispatch]~^^^ ERROR E0038 + //~^ ERROR E0038 + //~| ERROR E0038 } fn main() { } diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.stderr similarity index 86% rename from src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr rename to src/test/ui/kindck/kindck-inherited-copy-bound.stderr index a93f4686496ac..27901d0692799 100644 --- a/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr +++ b/src/test/ui/kindck/kindck-inherited-copy-bound.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied - --> $DIR/kindck-inherited-copy-bound.rs:21:16 + --> $DIR/kindck-inherited-copy-bound.rs:18:16 | LL | fn take_param(foo: &T) { } | ---------- --- required by this bound in `take_param` @@ -10,7 +10,7 @@ LL | take_param(&x); = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/kindck-inherited-copy-bound.rs:28:19 + --> $DIR/kindck-inherited-copy-bound.rs:24:19 | LL | let z = &x as &dyn Foo; | ^^^^^^^^ the trait `Foo` cannot be made into an object @@ -18,14 +18,13 @@ LL | let z = &x as &dyn Foo; = note: the trait cannot require that `Self : Sized` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/kindck-inherited-copy-bound.rs:28:13 + --> $DIR/kindck-inherited-copy-bound.rs:24:13 | LL | let z = &x as &dyn Foo; | ^^ the trait `Foo` cannot be made into an object | = note: the trait cannot require that `Self : Sized` = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box<{integer}>` - = note: required by cast to type `&dyn Foo` error: aborting due to 3 previous errors diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr index 38c7393e136a6..e990f705af3f9 100644 --- a/src/test/ui/lexical-scopes.stderr +++ b/src/test/ui/lexical-scopes.stderr @@ -16,5 +16,4 @@ LL | Foo::f(); error: aborting due to 2 previous errors -Some errors have detailed explanations: E0574, E0599. -For more information about an error, try `rustc --explain E0574`. +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr index b4011990b68e6..35d63c1727651 100644 --- a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr +++ b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr @@ -6,7 +6,7 @@ LL | ref_obj(x) | = note: expected type `&std::boxed::Box<(dyn std::ops::Fn() + 'static)>` found type `&std::boxed::Box<(dyn std::ops::Fn() + 'a)>` -note: the lifetime `'a` as defined on the function body at 32:10... +note: the lifetime 'a as defined on the function body at 32:10... --> $DIR/lifetime-bound-will-change-warning.rs:32:10 | LL | fn test2<'a>(x: &'a Box) { @@ -21,7 +21,7 @@ LL | lib::ref_obj(x) | = note: expected type `&std::boxed::Box<(dyn std::ops::Fn() + 'static)>` found type `&std::boxed::Box<(dyn std::ops::Fn() + 'a)>` -note: the lifetime `'a` as defined on the function body at 37:12... +note: the lifetime 'a as defined on the function body at 37:12... --> $DIR/lifetime-bound-will-change-warning.rs:37:12 | LL | fn test2cc<'a>(x: &'a Box) { diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.rs b/src/test/ui/lint/lint-exceeding-bitshifts2.rs index 2c213daddd752..69b627355b801 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts2.rs +++ b/src/test/ui/lint/lint-exceeding-bitshifts2.rs @@ -8,7 +8,7 @@ fn main() { let n = 1u8 << (4+3); let n = 1u8 << (4+4); //~ ERROR: attempt to shift left with overflow let n = 1i64 >> [63][0]; - let n = 1i64 >> [64][0]; //~ ERROR: attempt to shift right with overflow + let n = 1i64 >> [64][0]; // should be linting, needs to wait for const propagation #[cfg(target_pointer_width = "32")] const BITS: usize = 32; diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr index d9c76d233d03e..cb96982a78930 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr +++ b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr @@ -10,12 +10,6 @@ note: lint level defined here LL | #![deny(exceeding_bitshifts, const_err)] | ^^^^^^^^^^^^^^^^^^^ -error: attempt to shift right with overflow - --> $DIR/lint-exceeding-bitshifts2.rs:11:15 - | -LL | let n = 1i64 >> [64][0]; - | ^^^^^^^^^^^^^^^ - error: attempt to shift left with overflow --> $DIR/lint-exceeding-bitshifts2.rs:17:15 | @@ -28,5 +22,5 @@ error: attempt to shift left with overflow LL | let n = 1_usize << BITS; | ^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/lint-non-camel-case-types.stderr b/src/test/ui/lint/lint-non-camel-case-types.stderr index 177f8c8fe9b63..432a16debc698 100644 --- a/src/test/ui/lint/lint-non-camel-case-types.stderr +++ b/src/test/ui/lint/lint-non-camel-case-types.stderr @@ -14,25 +14,25 @@ error: type `foo` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:7:8 | LL | struct foo { - | ^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo` + | ^^^ help: convert the identifier to upper camel case: `Foo` error: type `foo2` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:11:6 | LL | enum foo2 { - | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo2` + | ^^^^ help: convert the identifier to upper camel case: `Foo2` error: type `foo3` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:15:8 | LL | struct foo3 { - | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo3` + | ^^^^ help: convert the identifier to upper camel case: `Foo3` error: type `foo4` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:19:6 | LL | type foo4 = isize; - | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo4` + | ^^^^ help: convert the identifier to upper camel case: `Foo4` error: variant `bar` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:22:5 @@ -44,7 +44,7 @@ error: trait `foo6` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:25:7 | LL | trait foo6 { - | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo6` + | ^^^^ help: convert the identifier to upper camel case: `Foo6` error: type parameter `ty` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:29:6 diff --git a/src/test/ui/lint/lint-non-snake-case-functions.stderr b/src/test/ui/lint/lint-non-snake-case-functions.stderr index c5eca89debb82..49cbfa9412610 100644 --- a/src/test/ui/lint/lint-non-snake-case-functions.stderr +++ b/src/test/ui/lint/lint-non-snake-case-functions.stderr @@ -38,7 +38,7 @@ error: trait method `a_b_C` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:25:8 | LL | fn a_b_C(&self) {} - | ^^^^^ help: convert the identifier to snake case (notice the capitalization): `a_b_c` + | ^^^^^ help: convert the identifier to snake case: `a_b_c` error: trait method `something__else` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:28:8 @@ -50,13 +50,13 @@ error: function `Cookie` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:38:4 | LL | fn Cookie() {} - | ^^^^^^ help: convert the identifier to snake case (notice the capitalization): `cookie` + | ^^^^^^ help: convert the identifier to snake case: `cookie` error: function `bi_S_Cuit` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:41:8 | LL | pub fn bi_S_Cuit() {} - | ^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `bi_s_cuit` + | ^^^^^^^^^ help: convert the identifier to snake case: `bi_s_cuit` error: aborting due to 9 previous errors diff --git a/src/test/ui/lint/lint-non-uppercase-statics.stderr b/src/test/ui/lint/lint-non-uppercase-statics.stderr index ceb83d08f2777..8b477276efc93 100644 --- a/src/test/ui/lint/lint-non-uppercase-statics.stderr +++ b/src/test/ui/lint/lint-non-uppercase-statics.stderr @@ -2,7 +2,7 @@ error: static variable `foo` should have an upper case name --> $DIR/lint-non-uppercase-statics.rs:4:8 | LL | static foo: isize = 1; - | ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO` + | ^^^ help: convert the identifier to upper case: `FOO` | note: lint level defined here --> $DIR/lint-non-uppercase-statics.rs:1:11 diff --git a/src/test/ui/lint/lint-unused-variables.rs b/src/test/ui/lint/lint-unused-variables.rs index 6850e999242ea..1a6b5183f0fae 100644 --- a/src/test/ui/lint/lint-unused-variables.rs +++ b/src/test/ui/lint/lint-unused-variables.rs @@ -29,11 +29,6 @@ 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( @@ -42,11 +37,6 @@ 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( @@ -55,11 +45,6 @@ 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 f8419bf506660..7ed5669e33c24 100644 --- a/src/test/ui/lint/lint-unused-variables.stderr +++ b/src/test/ui/lint/lint-unused-variables.stderr @@ -17,25 +17,19 @@ LL | b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `a` - --> $DIR/lint-unused-variables.rs:68:9 + --> $DIR/lint-unused-variables.rs:53:9 | LL | a: i32, | ^ help: consider prefixing with an underscore: `_a` error: unused variable: `b` - --> $DIR/lint-unused-variables.rs:74:9 + --> $DIR/lint-unused-variables.rs:59:9 | LL | b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `b` - --> $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 + --> $DIR/lint-unused-variables.rs:37:9 | LL | b: i32, | ^ help: consider prefixing with an underscore: `_b` @@ -53,22 +47,10 @@ LL | b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `b` - --> $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 + --> $DIR/lint-unused-variables.rs:45:9 | LL | b: i32, | ^ help: consider prefixing with an underscore: `_b` -error: aborting due to 11 previous errors +error: aborting due to 8 previous errors diff --git a/src/test/ui/lint/lint-uppercase-variables.stderr b/src/test/ui/lint/lint-uppercase-variables.stderr index f614d5d71f88c..9ea3795f89e6c 100644 --- a/src/test/ui/lint/lint-uppercase-variables.stderr +++ b/src/test/ui/lint/lint-uppercase-variables.stderr @@ -21,7 +21,7 @@ error: structure field `X` should have a snake case name --> $DIR/lint-uppercase-variables.rs:10:5 | LL | X: usize - | ^ help: convert the identifier to snake case (notice the capitalization): `x` + | ^ help: convert the identifier to snake case: `x` | note: lint level defined here --> $DIR/lint-uppercase-variables.rs:3:9 @@ -33,7 +33,7 @@ error: variable `Xx` should have a snake case name --> $DIR/lint-uppercase-variables.rs:13:9 | LL | fn test(Xx: usize) { - | ^^ help: convert the identifier to snake case (notice the capitalization): `xx` + | ^^ help: convert the identifier to snake case: `xx` error: variable `Test` should have a snake case name --> $DIR/lint-uppercase-variables.rs:18:9 @@ -45,7 +45,7 @@ error: variable `Foo` should have a snake case name --> $DIR/lint-uppercase-variables.rs:22:9 | LL | Foo => {} - | ^^^ help: convert the identifier to snake case (notice the capitalization): `foo` + | ^^^ help: convert the identifier to snake case: `foo` error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/must_use-unit.rs b/src/test/ui/lint/must_use-unit.rs index 4dd4798abb7ce..92568252164f6 100644 --- a/src/test/ui/lint/must_use-unit.rs +++ b/src/test/ui/lint/must_use-unit.rs @@ -1,4 +1,5 @@ #![feature(never_type)] + #![deny(unused_must_use)] #[must_use] diff --git a/src/test/ui/lint/must_use-unit.stderr b/src/test/ui/lint/must_use-unit.stderr index 0a9939b2015b7..f6229c0442f99 100644 --- a/src/test/ui/lint/must_use-unit.stderr +++ b/src/test/ui/lint/must_use-unit.stderr @@ -1,17 +1,17 @@ error: unused return value of `foo` that must be used - --> $DIR/must_use-unit.rs:13:5 + --> $DIR/must_use-unit.rs:14:5 | LL | foo(); | ^^^^^^ | note: lint level defined here - --> $DIR/must_use-unit.rs:2:9 + --> $DIR/must_use-unit.rs:3:9 | LL | #![deny(unused_must_use)] | ^^^^^^^^^^^^^^^ error: unused return value of `bar` that must be used - --> $DIR/must_use-unit.rs:15:5 + --> $DIR/must_use-unit.rs:16:5 | LL | bar(); | ^^^^^^ diff --git a/src/test/ui/lint/not_found.stderr b/src/test/ui/lint/not_found.stderr index 5016d9b97d69e..70d49a4e69ca0 100644 --- a/src/test/ui/lint/not_found.stderr +++ b/src/test/ui/lint/not_found.stderr @@ -16,5 +16,5 @@ warning: unknown lint: `Warnings` --> $DIR/not_found.rs:10:8 | LL | #[deny(Warnings)] - | ^^^^^^^^ help: did you mean (notice the capitalization): `warnings` + | ^^^^^^^^ help: did you mean: `warnings` diff --git a/src/test/ui/lint/reasons.stderr b/src/test/ui/lint/reasons.stderr index 139b3f13fd6b2..cb5f4ddf47b63 100644 --- a/src/test/ui/lint/reasons.stderr +++ b/src/test/ui/lint/reasons.stderr @@ -15,7 +15,7 @@ warning: variable `Social_exchange_psychology` should have a snake case name --> $DIR/reasons.rs:30:9 | LL | let Social_exchange_psychology = CheaterDetectionMechanism {}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `social_exchange_psychology` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `social_exchange_psychology` | = note: people shouldn't have to change their usual style habits to contribute to our project 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 index 2160df51a8375..5f289c0914d6e 100644 --- a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr +++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr @@ -1,4 +1,4 @@ -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) }] +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 | diff --git a/src/test/ui/lint/unused_parens_json_suggestion.fixed b/src/test/ui/lint/unused_parens_json_suggestion.fixed index 15ee19755bffc..427407119102c 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.fixed +++ b/src/test/ui/lint/unused_parens_json_suggestion.fixed @@ -1,4 +1,5 @@ -// compile-flags: --error-format json -Zunstable-options +// compile-flags: --error-format pretty-json -Zunstable-options +// build-pass (FIXME(62277): could be check-pass?) // run-rustfix // The output for humans should just highlight the whole span without showing @@ -7,13 +8,13 @@ // stripping away any starting or ending parenthesis characters—hence this // test of the JSON error format. -#![deny(unused_parens)] +#![warn(unused_parens)] #![allow(unreachable_code)] fn main() { // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not // the malformed `1 / (2 + 3` - let _a = 1 / (2 + 3); //~ERROR unnecessary parentheses + let _a = 1 / (2 + 3); f(); } diff --git a/src/test/ui/lint/unused_parens_json_suggestion.rs b/src/test/ui/lint/unused_parens_json_suggestion.rs index d72df21e09ae2..87192503986c4 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.rs +++ b/src/test/ui/lint/unused_parens_json_suggestion.rs @@ -1,4 +1,5 @@ -// compile-flags: --error-format json -Zunstable-options +// compile-flags: --error-format pretty-json -Zunstable-options +// build-pass (FIXME(62277): could be check-pass?) // run-rustfix // The output for humans should just highlight the whole span without showing @@ -7,13 +8,13 @@ // stripping away any starting or ending parenthesis characters—hence this // test of the JSON error format. -#![deny(unused_parens)] +#![warn(unused_parens)] #![allow(unreachable_code)] fn main() { // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not // the malformed `1 / (2 + 3` - let _a = (1 / (2 + 3)); //~ERROR unnecessary parentheses + let _a = (1 / (2 + 3)); f(); } diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr index c503c100808db..256c7555c908b 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.stderr +++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr @@ -1,16 +1,106 @@ -{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":609,"line_start":16,"line_end":16,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3)); - --> $DIR/unused_parens_json_suggestion.rs:16:14 +{ + "message": "unnecessary parentheses around assigned value", + "code": { + "code": "unused_parens", + "explanation": null + }, + "level": "warning", + "spans": [ + { + "file_name": "$DIR/unused_parens_json_suggestion.rs", + "byte_start": 654, + "byte_end": 667, + "line_start": 17, + "line_end": 17, + "column_start": 14, + "column_end": 27, + "is_primary": true, + "text": [ + { + "text": " let _a = (1 / (2 + 3));", + "highlight_start": 14, + "highlight_end": 27 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "lint level defined here", + "code": null, + "level": "note", + "spans": [ + { + "file_name": "$DIR/unused_parens_json_suggestion.rs", + "byte_start": 472, + "byte_end": 485, + "line_start": 11, + "line_end": 11, + "column_start": 9, + "column_end": 22, + "is_primary": true, + "text": [ + { + "text": "#![warn(unused_parens)]", + "highlight_start": 9, + "highlight_end": 22 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [], + "rendered": null + }, + { + "message": "remove these parentheses", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "$DIR/unused_parens_json_suggestion.rs", + "byte_start": 654, + "byte_end": 667, + "line_start": 17, + "line_end": 17, + "column_start": 14, + "column_end": 27, + "is_primary": true, + "text": [ + { + "text": " let _a = (1 / (2 + 3));", + "highlight_start": 14, + "highlight_end": 27 + } + ], + "label": null, + "suggested_replacement": "1 / (2 + 3)", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "warning: unnecessary parentheses around assigned value + --> $DIR/unused_parens_json_suggestion.rs:17:14 | LL | let _a = (1 / (2 + 3)); | ^^^^^^^^^^^^^ help: remove these parentheses | note: lint level defined here - --> $DIR/unused_parens_json_suggestion.rs:10:9 + --> $DIR/unused_parens_json_suggestion.rs:11:9 | -LL | #![deny(unused_parens)] +LL | #![warn(unused_parens)] | ^^^^^^^^^^^^^ -"} -{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error - -"} +" +} diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed b/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed index 1d891d328dd5a..2459eb1ac5cb8 100644 --- a/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed +++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed @@ -1,4 +1,5 @@ -// compile-flags: --error-format json -Zunstable-options +// compile-flags: --error-format pretty-json -Zunstable-options +// build-pass // run-rustfix // The output for humans should just highlight the whole span without showing @@ -7,14 +8,14 @@ // stripping away any starting or ending parenthesis characters—hence this // test of the JSON error format. -#![deny(unused_parens)] +#![warn(unused_parens)] #![allow(unreachable_code)] fn main() { let _b = false; - if _b { //~ ERROR unnecessary parentheses + if _b { println!("hello"); } @@ -25,29 +26,29 @@ fn main() { fn f() -> bool { let c = false; - if c { //~ ERROR unnecessary parentheses + if c { println!("next"); } - if c { //~ ERROR unnecessary parentheses + if c { println!("prev"); } while false && true { - if c { //~ ERROR unnecessary parentheses + if c { println!("norm"); } } - while true && false { //~ ERROR unnecessary parentheses - for _ in 0 .. 3 { //~ ERROR unnecessary parentheses + while true && false { + for _ in 0 .. 3 { println!("e~") } } - for _ in 0 .. 3 { //~ ERROR unnecessary parentheses - while true && false { //~ ERROR unnecessary parentheses + for _ in 0 .. 3 { + while true && false { println!("e~") } } diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.rs b/src/test/ui/lint/unused_parens_remove_json_suggestion.rs index 494cd18450630..0e9869b67d590 100644 --- a/src/test/ui/lint/unused_parens_remove_json_suggestion.rs +++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.rs @@ -1,4 +1,5 @@ -// compile-flags: --error-format json -Zunstable-options +// compile-flags: --error-format pretty-json -Zunstable-options +// build-pass // run-rustfix // The output for humans should just highlight the whole span without showing @@ -7,14 +8,14 @@ // stripping away any starting or ending parenthesis characters—hence this // test of the JSON error format. -#![deny(unused_parens)] +#![warn(unused_parens)] #![allow(unreachable_code)] fn main() { let _b = false; - if (_b) { //~ ERROR unnecessary parentheses + if (_b) { println!("hello"); } @@ -25,29 +26,29 @@ fn main() { fn f() -> bool { let c = false; - if(c) { //~ ERROR unnecessary parentheses + if(c) { println!("next"); } - if (c){ //~ ERROR unnecessary parentheses + if (c){ println!("prev"); } while (false && true){ - if (c) { //~ ERROR unnecessary parentheses + if (c) { println!("norm"); } } - while(true && false) { //~ ERROR unnecessary parentheses - for _ in (0 .. 3){ //~ ERROR unnecessary parentheses + while(true && false) { + for _ in (0 .. 3){ println!("e~") } } - for _ in (0 .. 3) { //~ ERROR unnecessary parentheses - while (true && false) { //~ ERROR unnecessary parentheses + for _ in (0 .. 3) { + while (true && false) { println!("e~") } } diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr index 873f105435e08..b4eab200dd016 100644 --- a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr +++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr @@ -1,72 +1,666 @@ -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":504,"line_start":17,"line_end":17,"column_start":8,"column_end":12,"is_primary":true,"text":[{"text":" if (_b) { - --> $DIR/unused_parens_remove_json_suggestion.rs:17:8 +{ + "message": "unnecessary parentheses around `if` condition", + "code": { + "code": "unused_parens", + "explanation": null + }, + "level": "warning", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 521, + "byte_end": 525, + "line_start": 18, + "line_end": 18, + "column_start": 8, + "column_end": 12, + "is_primary": true, + "text": [ + { + "text": " if (_b) {", + "highlight_start": 8, + "highlight_end": 12 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "lint level defined here", + "code": null, + "level": "note", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 435, + "byte_end": 448, + "line_start": 11, + "line_end": 11, + "column_start": 9, + "column_end": 22, + "is_primary": true, + "text": [ + { + "text": "#![warn(unused_parens)]", + "highlight_start": 9, + "highlight_end": 22 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [], + "rendered": null + }, + { + "message": "remove these parentheses", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 521, + "byte_end": 525, + "line_start": 18, + "line_end": 18, + "column_start": 8, + "column_end": 12, + "is_primary": true, + "text": [ + { + "text": " if (_b) {", + "highlight_start": 8, + "highlight_end": 12 + } + ], + "label": null, + "suggested_replacement": "_b", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "warning: unnecessary parentheses around `if` condition + --> $DIR/unused_parens_remove_json_suggestion.rs:18:8 | LL | if (_b) { | ^^^^ help: remove these parentheses | note: lint level defined here - --> $DIR/unused_parens_remove_json_suggestion.rs:10:9 + --> $DIR/unused_parens_remove_json_suggestion.rs:11:9 | -LL | #![deny(unused_parens)] +LL | #![warn(unused_parens)] | ^^^^^^^^^^^^^ -"} -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":634,"line_start":28,"line_end":28,"column_start":7,"column_end":10,"is_primary":true,"text":[{"text":" if(c) { - --> $DIR/unused_parens_remove_json_suggestion.rs:28:7 +" +} +{ + "message": "unnecessary parentheses around `if` condition", + "code": { + "code": "unused_parens", + "explanation": null + }, + "level": "warning", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 618, + "byte_end": 621, + "line_start": 29, + "line_end": 29, + "column_start": 7, + "column_end": 10, + "is_primary": true, + "text": [ + { + "text": " if(c) {", + "highlight_start": 7, + "highlight_end": 10 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "remove these parentheses", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 618, + "byte_end": 621, + "line_start": 29, + "line_end": 29, + "column_start": 7, + "column_end": 10, + "is_primary": true, + "text": [ + { + "text": " if(c) {", + "highlight_start": 7, + "highlight_end": 10 + } + ], + "label": null, + "suggested_replacement": " c", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "warning: unnecessary parentheses around `if` condition + --> $DIR/unused_parens_remove_json_suggestion.rs:29:7 | LL | if(c) { | ^^^ help: remove these parentheses -"} -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":714,"line_start":32,"line_end":32,"column_start":8,"column_end":11,"is_primary":true,"text":[{"text":" if (c){ - --> $DIR/unused_parens_remove_json_suggestion.rs:32:8 +" +} +{ + "message": "unnecessary parentheses around `if` condition", + "code": { + "code": "unused_parens", + "explanation": null + }, + "level": "warning", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 664, + "byte_end": 667, + "line_start": 33, + "line_end": 33, + "column_start": 8, + "column_end": 11, + "is_primary": true, + "text": [ + { + "text": " if (c){", + "highlight_start": 8, + "highlight_end": 11 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "remove these parentheses", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 664, + "byte_end": 667, + "line_start": 33, + "line_end": 33, + "column_start": 8, + "column_end": 11, + "is_primary": true, + "text": [ + { + "text": " if (c){", + "highlight_start": 8, + "highlight_end": 11 + } + ], + "label": null, + "suggested_replacement": "c ", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "warning: unnecessary parentheses around `if` condition + --> $DIR/unused_parens_remove_json_suggestion.rs:33:8 | LL | if (c){ | ^^^ help: remove these parentheses -"} -{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":"false && true ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition - --> $DIR/unused_parens_remove_json_suggestion.rs:36:11 +" +} +{ + "message": "unnecessary parentheses around `while` condition", + "code": { + "code": "unused_parens", + "explanation": null + }, + "level": "warning", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 712, + "byte_end": 727, + "line_start": 37, + "line_end": 37, + "column_start": 11, + "column_end": 26, + "is_primary": true, + "text": [ + { + "text": " while (false && true){", + "highlight_start": 11, + "highlight_end": 26 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "remove these parentheses", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 712, + "byte_end": 727, + "line_start": 37, + "line_end": 37, + "column_start": 11, + "column_end": 26, + "is_primary": true, + "text": [ + { + "text": " while (false && true){", + "highlight_start": 11, + "highlight_end": 26 + } + ], + "label": null, + "suggested_replacement": "false && true ", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "warning: unnecessary parentheses around `while` condition + --> $DIR/unused_parens_remove_json_suggestion.rs:37:11 | LL | while (false && true){ | ^^^^^^^^^^^^^^^ help: remove these parentheses -"} -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":824,"line_start":37,"line_end":37,"column_start":12,"column_end":15,"is_primary":true,"text":[{"text":" if (c) { - --> $DIR/unused_parens_remove_json_suggestion.rs:37:12 +" +} +{ + "message": "unnecessary parentheses around `if` condition", + "code": { + "code": "unused_parens", + "explanation": null + }, + "level": "warning", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 740, + "byte_end": 743, + "line_start": 38, + "line_end": 38, + "column_start": 12, + "column_end": 15, + "is_primary": true, + "text": [ + { + "text": " if (c) {", + "highlight_start": 12, + "highlight_end": 15 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "remove these parentheses", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 740, + "byte_end": 743, + "line_start": 38, + "line_end": 38, + "column_start": 12, + "column_end": 15, + "is_primary": true, + "text": [ + { + "text": " if (c) {", + "highlight_start": 12, + "highlight_end": 15 + } + ], + "label": null, + "suggested_replacement": "c", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "warning: unnecessary parentheses around `if` condition + --> $DIR/unused_parens_remove_json_suggestion.rs:38:12 | LL | if (c) { | ^^^ help: remove these parentheses -"} -{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":933,"line_start":43,"line_end":43,"column_start":10,"column_end":25,"is_primary":true,"text":[{"text":" while(true && false) { - --> $DIR/unused_parens_remove_json_suggestion.rs:43:10 +" +} +{ + "message": "unnecessary parentheses around `while` condition", + "code": { + "code": "unused_parens", + "explanation": null + }, + "level": "warning", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 803, + "byte_end": 818, + "line_start": 44, + "line_end": 44, + "column_start": 10, + "column_end": 25, + "is_primary": true, + "text": [ + { + "text": " while(true && false) {", + "highlight_start": 10, + "highlight_end": 25 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "remove these parentheses", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 803, + "byte_end": 818, + "line_start": 44, + "line_end": 44, + "column_start": 10, + "column_end": 25, + "is_primary": true, + "text": [ + { + "text": " while(true && false) {", + "highlight_start": 10, + "highlight_end": 25 + } + ], + "label": null, + "suggested_replacement": " true && false", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "warning: unnecessary parentheses around `while` condition + --> $DIR/unused_parens_remove_json_suggestion.rs:44:10 | LL | while(true && false) { | ^^^^^^^^^^^^^^^ help: remove these parentheses -"} -{"message":"unnecessary parentheses around `for` head expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){ - --> $DIR/unused_parens_remove_json_suggestion.rs:44:18 +" +} +{ + "message": "unnecessary parentheses around `for` head expression", + "code": { + "code": "unused_parens", + "explanation": null + }, + "level": "warning", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 838, + "byte_end": 846, + "line_start": 45, + "line_end": 45, + "column_start": 18, + "column_end": 26, + "is_primary": true, + "text": [ + { + "text": " for _ in (0 .. 3){", + "highlight_start": 18, + "highlight_end": 26 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "remove these parentheses", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 838, + "byte_end": 846, + "line_start": 45, + "line_end": 45, + "column_start": 18, + "column_end": 26, + "is_primary": true, + "text": [ + { + "text": " for _ in (0 .. 3){", + "highlight_start": 18, + "highlight_end": 26 + } + ], + "label": null, + "suggested_replacement": "0 .. 3 ", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "warning: unnecessary parentheses around `for` head expression + --> $DIR/unused_parens_remove_json_suggestion.rs:45:18 | LL | for _ in (0 .. 3){ | ^^^^^^^^ help: remove these parentheses -"} -{"message":"unnecessary parentheses around `for` head expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) { - --> $DIR/unused_parens_remove_json_suggestion.rs:49:14 +" +} +{ + "message": "unnecessary parentheses around `for` head expression", + "code": { + "code": "unused_parens", + "explanation": null + }, + "level": "warning", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 905, + "byte_end": 913, + "line_start": 50, + "line_end": 50, + "column_start": 14, + "column_end": 22, + "is_primary": true, + "text": [ + { + "text": " for _ in (0 .. 3) {", + "highlight_start": 14, + "highlight_end": 22 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "remove these parentheses", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 905, + "byte_end": 913, + "line_start": 50, + "line_end": 50, + "column_start": 14, + "column_end": 22, + "is_primary": true, + "text": [ + { + "text": " for _ in (0 .. 3) {", + "highlight_start": 14, + "highlight_end": 22 + } + ], + "label": null, + "suggested_replacement": "0 .. 3", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "warning: unnecessary parentheses around `for` head expression + --> $DIR/unused_parens_remove_json_suggestion.rs:50:14 | LL | for _ in (0 .. 3) { | ^^^^^^^^ help: remove these parentheses -"} -{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1162,"line_start":50,"line_end":50,"column_start":15,"column_end":30,"is_primary":true,"text":[{"text":" while (true && false) { - --> $DIR/unused_parens_remove_json_suggestion.rs:50:15 +" +} +{ + "message": "unnecessary parentheses around `while` condition", + "code": { + "code": "unused_parens", + "explanation": null + }, + "level": "warning", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 930, + "byte_end": 945, + "line_start": 51, + "line_end": 51, + "column_start": 15, + "column_end": 30, + "is_primary": true, + "text": [ + { + "text": " while (true && false) {", + "highlight_start": 15, + "highlight_end": 30 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "remove these parentheses", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", + "byte_start": 930, + "byte_end": 945, + "line_start": 51, + "line_end": 51, + "column_start": 15, + "column_end": 30, + "is_primary": true, + "text": [ + { + "text": " while (true && false) {", + "highlight_start": 15, + "highlight_end": 30 + } + ], + "label": null, + "suggested_replacement": "true && false", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "warning: unnecessary parentheses around `while` condition + --> $DIR/unused_parens_remove_json_suggestion.rs:51:15 | LL | while (true && false) { | ^^^^^^^^^^^^^^^ help: remove these parentheses -"} -{"message":"aborting due to 9 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 9 previous errors - -"} +" +} diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr index 1da5acc966163..678c88849b561 100644 --- a/src/test/ui/lint/use_suggestion_json.stderr +++ b/src/test/ui/lint/use_suggestion_json.stderr @@ -395,7 +395,7 @@ mod foo { \u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m \u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0muse std::collections::hash_map::Iter;\u001b[0m \u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m -\u001b[0m and 8 other candidates\u001b[0m +\u001b[0mand 8 other candidates\u001b[0m " } diff --git a/src/test/ui/lub-if.stderr b/src/test/ui/lub-if.stderr index 0a4744013a62c..26f756c91833b 100644 --- a/src/test/ui/lub-if.stderr +++ b/src/test/ui/lub-if.stderr @@ -5,7 +5,7 @@ LL | s | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 23:17 +note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 23:17 --> $DIR/lub-if.rs:23:17 | LL | pub fn opt_str2<'a>(maybestr: &'a Option) -> &'static str { @@ -18,7 +18,7 @@ LL | s | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 32:17 +note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 32:17 --> $DIR/lub-if.rs:32:17 | LL | pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { diff --git a/src/test/ui/lub-match.stderr b/src/test/ui/lub-match.stderr index 168a389446921..0cb0a23c6f2df 100644 --- a/src/test/ui/lub-match.stderr +++ b/src/test/ui/lub-match.stderr @@ -5,7 +5,7 @@ LL | s | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 25:17 +note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 25:17 --> $DIR/lub-match.rs:25:17 | LL | pub fn opt_str2<'a>(maybestr: &'a Option) -> &'static str { @@ -18,7 +18,7 @@ LL | s | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 35:17 +note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 35:17 --> $DIR/lub-match.rs:35:17 | LL | pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { diff --git a/src/test/ui/macros/issue-54441.rs b/src/test/ui/macros/issue-54441.rs index afdf76b7b580f..b45aedb549ecd 100644 --- a/src/test/ui/macros/issue-54441.rs +++ b/src/test/ui/macros/issue-54441.rs @@ -1,3 +1,5 @@ +#![feature(macros_in_extern)] + macro_rules! m { () => { let //~ ERROR expected diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr index af0ee3ae8eca3..b0fafdc3b6326 100644 --- a/src/test/ui/macros/issue-54441.stderr +++ b/src/test/ui/macros/issue-54441.stderr @@ -1,5 +1,5 @@ error: expected one of `crate`, `fn`, `pub`, `static`, or `type`, found `let` - --> $DIR/issue-54441.rs:3:9 + --> $DIR/issue-54441.rs:5:9 | LL | let | ^^^ unexpected token diff --git a/src/test/ui/macros/macro-comma-behavior-rpass.rs b/src/test/ui/macros/macro-comma-behavior-rpass.rs index 1c791bb1ca3d6..9f1a31d1ae274 100644 --- a/src/test/ui/macros/macro-comma-behavior-rpass.rs +++ b/src/test/ui/macros/macro-comma-behavior-rpass.rs @@ -13,8 +13,6 @@ // compile-flags: --test -C debug_assertions=yes // revisions: std core -// ignore-emscripten compiled with panic=abort by default - #![cfg_attr(core, no_std)] #[cfg(std)] use std::fmt; diff --git a/src/test/ui/macros/macro-first-set.rs b/src/test/ui/macros/macro-first-set.rs index eb2504d4bfdb7..34529cdaa64f1 100644 --- a/src/test/ui/macros/macro-first-set.rs +++ b/src/test/ui/macros/macro-first-set.rs @@ -252,6 +252,12 @@ test_path!(::std); test_path!(std::u8,); test_path!(any, super, super::super::self::path, X::Z<'a, T=U>); +macro_rules! test_meta_block { + ($($m:meta)* $b:block) => {}; +} + +test_meta_block!(windows {}); + macro_rules! test_lifetime { (1. $($l:lifetime)* $($b:block)*) => {}; (2. $($b:block)* $($l:lifetime)*) => {}; diff --git a/src/test/ui/macros/macro-meta-items-modern.rs b/src/test/ui/macros/macro-meta-items-modern.rs deleted file mode 100644 index bc6938d4a6c9a..0000000000000 --- a/src/test/ui/macros/macro-meta-items-modern.rs +++ /dev/null @@ -1,11 +0,0 @@ -// check-pass - -macro_rules! check { ($meta:meta) => () } - -check!(meta(a b c d)); -check!(meta[a b c d]); -check!(meta { a b c d }); -check!(meta); -check!(meta = 0); - -fn main() {} diff --git a/src/test/ui/macros/macros-in-extern-rpass.rs b/src/test/ui/macros/macros-in-extern-rpass.rs new file mode 100644 index 0000000000000..28abef5cf4edc --- /dev/null +++ b/src/test/ui/macros/macros-in-extern-rpass.rs @@ -0,0 +1,30 @@ +// run-pass +// ignore-wasm32 + +#![feature(decl_macro, macros_in_extern)] + +macro_rules! returns_isize( + ($ident:ident) => ( + fn $ident() -> isize; + ) +); + +macro takes_u32_returns_u32($ident:ident) { + fn $ident (arg: u32) -> u32; +} + +macro_rules! emits_nothing( + () => () +); + +fn main() { + assert_eq!(unsafe { rust_get_test_int() }, 1isize); + assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEFu32); +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern { + returns_isize!(rust_get_test_int); + takes_u32_returns_u32!(rust_dbg_extern_identity_u32); + emits_nothing!(); +} diff --git a/src/test/ui/macros/same-sequence-span.rs b/src/test/ui/macros/same-sequence-span.rs index e0bb4d98525b9..a4f70b6b68d1e 100644 --- a/src/test/ui/macros/same-sequence-span.rs +++ b/src/test/ui/macros/same-sequence-span.rs @@ -4,6 +4,7 @@ // left-hand side of a macro definition behave as if they had unique spans, and in particular that // they don't crash the compiler. +#![feature(proc_macro_hygiene)] #![allow(unused_macros)] extern crate proc_macro_sequence; diff --git a/src/test/ui/macros/same-sequence-span.stderr b/src/test/ui/macros/same-sequence-span.stderr index 896f579765f95..0eef4a2a678b6 100644 --- a/src/test/ui/macros/same-sequence-span.stderr +++ b/src/test/ui/macros/same-sequence-span.stderr @@ -1,5 +1,5 @@ error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments - --> $DIR/same-sequence-span.rs:14:18 + --> $DIR/same-sequence-span.rs:15:18 | LL | (1 $x:expr $($y:tt,)* | ^^^^^ not allowed after `expr` fragments @@ -7,7 +7,7 @@ LL | (1 $x:expr $($y:tt,)* = note: allowed there are: `=>`, `,` or `;` error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragments - --> $DIR/same-sequence-span.rs:15:18 + --> $DIR/same-sequence-span.rs:16:18 | LL | $(= $z:tt)* | ^ not allowed after `expr` fragments @@ -15,7 +15,7 @@ LL | $(= $z:tt)* = note: allowed there are: `=>`, `,` or `;` error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments - --> $DIR/same-sequence-span.rs:19:1 + --> $DIR/same-sequence-span.rs:20:1 | LL | proc_macro_sequence::make_foo!(); | ^-------------------------------- @@ -30,7 +30,7 @@ LL | | fn main() {} = note: allowed there are: `=>`, `,` or `;` error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragments - --> $DIR/same-sequence-span.rs:19:1 + --> $DIR/same-sequence-span.rs:20:1 | LL | proc_macro_sequence::make_foo!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/malformed/malformed-plugin-1.rs b/src/test/ui/malformed/malformed-plugin-1.rs index d4c1a2a16795b..28f6c8e7a6f67 100644 --- a/src/test/ui/malformed/malformed-plugin-1.rs +++ b/src/test/ui/malformed/malformed-plugin-1.rs @@ -1,5 +1,4 @@ #![feature(plugin)] #![plugin] //~ ERROR malformed `plugin` attribute -//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated fn main() {} diff --git a/src/test/ui/malformed/malformed-plugin-1.stderr b/src/test/ui/malformed/malformed-plugin-1.stderr index 3860864bd1336..a863cd4859656 100644 --- a/src/test/ui/malformed/malformed-plugin-1.stderr +++ b/src/test/ui/malformed/malformed-plugin-1.stderr @@ -4,13 +4,5 @@ error: malformed `plugin` attribute input LL | #![plugin] | ^^^^^^^^^^ help: must be of the form: `#[plugin(name|name(args))]` -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/malformed-plugin-1.rs:2:1 - | -LL | #![plugin] - | ^^^^^^^^^^ help: may be removed in a future compiler version - | - = note: `#[warn(deprecated)]` on by default - error: aborting due to previous error diff --git a/src/test/ui/malformed/malformed-plugin-2.rs b/src/test/ui/malformed/malformed-plugin-2.rs index ba80d97a3c276..8ec7a71da29b3 100644 --- a/src/test/ui/malformed/malformed-plugin-2.rs +++ b/src/test/ui/malformed/malformed-plugin-2.rs @@ -1,5 +1,4 @@ #![feature(plugin)] #![plugin="bleh"] //~ ERROR malformed `plugin` attribute -//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated fn main() {} diff --git a/src/test/ui/malformed/malformed-plugin-2.stderr b/src/test/ui/malformed/malformed-plugin-2.stderr index e4bca93f13b35..6eb0c50ca9398 100644 --- a/src/test/ui/malformed/malformed-plugin-2.stderr +++ b/src/test/ui/malformed/malformed-plugin-2.stderr @@ -4,13 +4,5 @@ error: malformed `plugin` attribute input LL | #![plugin="bleh"] | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[plugin(name|name(args))]` -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/malformed-plugin-2.rs:2:1 - | -LL | #![plugin="bleh"] - | ^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - | - = note: `#[warn(deprecated)]` on by default - error: aborting due to previous error diff --git a/src/test/ui/malformed/malformed-plugin-3.rs b/src/test/ui/malformed/malformed-plugin-3.rs index d2bd8f9f8dc47..c4713616b6258 100644 --- a/src/test/ui/malformed/malformed-plugin-3.rs +++ b/src/test/ui/malformed/malformed-plugin-3.rs @@ -1,5 +1,4 @@ #![feature(plugin)] #![plugin(foo="bleh")] //~ ERROR malformed `plugin` attribute -//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated fn main() {} diff --git a/src/test/ui/malformed/malformed-plugin-3.stderr b/src/test/ui/malformed/malformed-plugin-3.stderr index 7393072cb1ca3..f93fa0f65e85a 100644 --- a/src/test/ui/malformed/malformed-plugin-3.stderr +++ b/src/test/ui/malformed/malformed-plugin-3.stderr @@ -4,13 +4,5 @@ error[E0498]: malformed `plugin` attribute LL | #![plugin(foo="bleh")] | ^^^^^^^^^^^^^^^^^^^^^^ malformed attribute -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/malformed-plugin-3.rs:2:1 - | -LL | #![plugin(foo="bleh")] - | ^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - | - = note: `#[warn(deprecated)]` on by default - error: aborting due to previous error diff --git a/src/test/ui/match/match-range-fail-dominate.rs b/src/test/ui/match/match-range-fail-dominate.rs index 7de7b7e79be44..a0cc773d20edd 100644 --- a/src/test/ui/match/match-range-fail-dominate.rs +++ b/src/test/ui/match/match-range-fail-dominate.rs @@ -1,45 +1,39 @@ -#![deny(unreachable_patterns, overlapping_patterns)] +//error-pattern: unreachable +//error-pattern: unreachable +//error-pattern: unreachable +//error-pattern: unreachable +//error-pattern: unreachable + +#![deny(unreachable_patterns)] fn main() { match 5 { 1 ..= 10 => { } 5 ..= 6 => { } - //~^ ERROR unreachable pattern _ => {} }; match 5 { 3 ..= 6 => { } 4 ..= 6 => { } - //~^ ERROR unreachable pattern _ => {} }; match 5 { 4 ..= 6 => { } 4 ..= 6 => { } - //~^ ERROR unreachable pattern _ => {} }; match 'c' { 'A' ..= 'z' => {} 'a' ..= 'z' => {} - //~^ ERROR unreachable pattern _ => {} }; match 1.0f64 { 0.01f64 ..= 6.5f64 => {} - //~^ WARNING floating-point types cannot be used in patterns - //~| WARNING floating-point types cannot be used in patterns - //~| WARNING floating-point types cannot be used in patterns - //~| WARNING this was previously accepted by the compiler - //~| WARNING this was previously accepted by the compiler - //~| WARNING this was previously accepted by the compiler - 0.02f64 => {} //~ ERROR unreachable pattern - //~^ WARNING floating-point types cannot be used in patterns - //~| WARNING this was previously accepted by the compiler + 0.02f64 => {} _ => {} }; } diff --git a/src/test/ui/match/match-range-fail-dominate.stderr b/src/test/ui/match/match-range-fail-dominate.stderr index c15186d2558f2..d0ff4930a4519 100644 --- a/src/test/ui/match/match-range-fail-dominate.stderr +++ b/src/test/ui/match/match-range-fail-dominate.stderr @@ -1,35 +1,35 @@ error: unreachable pattern - --> $DIR/match-range-fail-dominate.rs:6:7 + --> $DIR/match-range-fail-dominate.rs:12:7 | LL | 5 ..= 6 => { } | ^^^^^^^ | note: lint level defined here - --> $DIR/match-range-fail-dominate.rs:1:9 + --> $DIR/match-range-fail-dominate.rs:7:9 | -LL | #![deny(unreachable_patterns, overlapping_patterns)] +LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/match-range-fail-dominate.rs:13:7 + --> $DIR/match-range-fail-dominate.rs:18:7 | LL | 4 ..= 6 => { } | ^^^^^^^ error: unreachable pattern - --> $DIR/match-range-fail-dominate.rs:20:7 + --> $DIR/match-range-fail-dominate.rs:24:7 | LL | 4 ..= 6 => { } | ^^^^^^^ error: unreachable pattern - --> $DIR/match-range-fail-dominate.rs:27:7 + --> $DIR/match-range-fail-dominate.rs:30:7 | LL | 'a' ..= 'z' => {} | ^^^^^^^^^^^ warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:33:7 + --> $DIR/match-range-fail-dominate.rs:35:7 | LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^^ @@ -39,7 +39,7 @@ LL | 0.01f64 ..= 6.5f64 => {} = note: for more information, see issue #41620 warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:33:19 + --> $DIR/match-range-fail-dominate.rs:35:19 | LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^ @@ -48,7 +48,7 @@ LL | 0.01f64 ..= 6.5f64 => {} = note: for more information, see issue #41620 warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:40:7 + --> $DIR/match-range-fail-dominate.rs:36:7 | LL | 0.02f64 => {} | ^^^^^^^ @@ -57,13 +57,13 @@ LL | 0.02f64 => {} = note: for more information, see issue #41620 error: unreachable pattern - --> $DIR/match-range-fail-dominate.rs:40:7 + --> $DIR/match-range-fail-dominate.rs:36:7 | LL | 0.02f64 => {} | ^^^^^^^ warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:33:7 + --> $DIR/match-range-fail-dominate.rs:35:7 | LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^^ diff --git a/src/test/ui/match/match-ref-mut-invariance.stderr b/src/test/ui/match/match-ref-mut-invariance.stderr index 0a020989d6f35..30bbb8d7800f9 100644 --- a/src/test/ui/match/match-ref-mut-invariance.stderr +++ b/src/test/ui/match/match-ref-mut-invariance.stderr @@ -6,12 +6,12 @@ LL | match self.0 { ref mut x => x } | = note: expected type `&'a mut &'a i32` found type `&'a mut &'b i32` -note: the lifetime `'a` as defined on the method body at 9:12... +note: the lifetime 'a as defined on the method body at 9:12... --> $DIR/match-ref-mut-invariance.rs:9:12 | LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 8:6 +note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 8:6 --> $DIR/match-ref-mut-invariance.rs:8:6 | LL | impl<'b> S<'b> { diff --git a/src/test/ui/match/match-ref-mut-let-invariance.stderr b/src/test/ui/match/match-ref-mut-let-invariance.stderr index 1bea9bce11e47..6ca222d9c2ffc 100644 --- a/src/test/ui/match/match-ref-mut-let-invariance.stderr +++ b/src/test/ui/match/match-ref-mut-let-invariance.stderr @@ -6,12 +6,12 @@ LL | x | = note: expected type `&'a mut &'a i32` found type `&'a mut &'b i32` -note: the lifetime `'a` as defined on the method body at 9:12... +note: the lifetime 'a as defined on the method body at 9:12... --> $DIR/match-ref-mut-let-invariance.rs:9:12 | LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 8:6 +note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 8:6 --> $DIR/match-ref-mut-let-invariance.rs:8:6 | LL | impl<'b> S<'b> { diff --git a/src/test/ui/match/non-exhaustive-defined-here.stderr b/src/test/ui/match/non-exhaustive-defined-here.stderr index e5f01174ac1bf..25b8bbdab2d8e 100644 --- a/src/test/ui/match/non-exhaustive-defined-here.stderr +++ b/src/test/ui/match/non-exhaustive-defined-here.stderr @@ -41,13 +41,6 @@ LL | | } ... LL | let E::A = e; | ^^^^ patterns `B` and `C` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let E::A = e { /* */ } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered --> $DIR/non-exhaustive-defined-here.rs:40:11 @@ -92,13 +85,6 @@ LL | | } ... LL | let E::A = e; | ^^^^ patterns `&B` and `&C` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let E::A = e { /* */ } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered --> $DIR/non-exhaustive-defined-here.rs:48:11 @@ -143,13 +129,6 @@ LL | | } ... LL | let E::A = e; | ^^^^ patterns `&&mut &B` and `&&mut &C` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let E::A = e { /* */ } - | error[E0004]: non-exhaustive patterns: `None` not covered --> $DIR/non-exhaustive-defined-here.rs:65:11 @@ -184,13 +163,6 @@ LL | | } ... LL | let Opt::Some(ref _x) = e; | ^^^^^^^^^^^^^^^^^ pattern `None` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let Opt::Some(ref _x) = e { /* */ } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/src/test/ui/maybe-bounds-where.stderr b/src/test/ui/maybe-bounds-where.stderr index 15cbce46f0a9b..78524cbabecd7 100644 --- a/src/test/ui/maybe-bounds-where.stderr +++ b/src/test/ui/maybe-bounds-where.stderr @@ -34,7 +34,7 @@ error[E0203]: type parameter has more than one relaxed default bound, only one i LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; | ^ -warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default. Only `?Sized` is supported --> $DIR/maybe-bounds-where.rs:15:11 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; diff --git a/src/test/ui/methods/method-path-in-pattern.rs b/src/test/ui/methods/method-path-in-pattern.rs index 21a91f3f32b24..fb1cf7f71e70a 100644 --- a/src/test/ui/methods/method-path-in-pattern.rs +++ b/src/test/ui/methods/method-path-in-pattern.rs @@ -23,10 +23,4 @@ fn main() { ::trait_bar => {} //~^ ERROR expected unit struct/variant or constant, found method `::trait_bar` } - if let Foo::bar = 0u32 {} - //~^ ERROR expected unit struct/variant or constant, found method `::bar` - if let ::bar = 0u32 {} - //~^ ERROR expected unit struct/variant or constant, found method `::bar` - if let Foo::trait_bar = 0u32 {} - //~^ ERROR expected unit struct/variant or constant, found method `::trait_bar` } diff --git a/src/test/ui/methods/method-path-in-pattern.stderr b/src/test/ui/methods/method-path-in-pattern.stderr index 257fff4c37dc0..3f53ad768825b 100644 --- a/src/test/ui/methods/method-path-in-pattern.stderr +++ b/src/test/ui/methods/method-path-in-pattern.stderr @@ -16,24 +16,5 @@ error[E0533]: expected unit struct/variant or constant, found method `::tra LL | ::trait_bar => {} | ^^^^^^^^^^^^^^^^ -error[E0533]: expected unit struct/variant or constant, found method `::bar` - --> $DIR/method-path-in-pattern.rs:26:12 - | -LL | if let Foo::bar = 0u32 {} - | ^^^^^^^^ - -error[E0533]: expected unit struct/variant or constant, found method `::bar` - --> $DIR/method-path-in-pattern.rs:28:12 - | -LL | if let ::bar = 0u32 {} - | ^^^^^^^^^^ - -error[E0533]: expected unit struct/variant or constant, found method `::trait_bar` - --> $DIR/method-path-in-pattern.rs:30:12 - | -LL | if let Foo::trait_bar = 0u32 {} - | ^^^^^^^^^^^^^^ - -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0533`. diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs b/src/test/ui/mir-dataflow/indirect-mutation-offset.rs deleted file mode 100644 index 8087a3e139915..0000000000000 --- a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs +++ /dev/null @@ -1,41 +0,0 @@ -// compile-flags: -Zunleash-the-miri-inside-of-you - -#![feature(core_intrinsics, rustc_attrs, const_raw_ptr_deref)] - -use std::cell::UnsafeCell; -use std::intrinsics::rustc_peek; - -#[repr(C)] -struct PartialInteriorMut { - zst: [i32; 0], - cell: UnsafeCell, -} - -#[rustc_mir(rustc_peek_indirectly_mutable,stop_after_dataflow)] -const BOO: i32 = { - let x = PartialInteriorMut { - zst: [], - cell: UnsafeCell::new(0), - }; - - let p_zst: *const _ = &x.zst ; // Doesn't cause `x` to get marked as indirectly mutable. - - let rmut_cell = unsafe { - // Take advantage of the fact that `zst` and `cell` are at the same location in memory. - // This trick would work with any size type if miri implemented `ptr::offset`. - let p_cell = p_zst as *const UnsafeCell; - - let pmut_cell = (*p_cell).get(); - &mut *pmut_cell - }; - - *rmut_cell = 42; // Mutates `x` indirectly even though `x` is not marked indirectly mutable!!! - let val = *rmut_cell; - unsafe { rustc_peek(x) }; //~ ERROR rustc_peek: bit not set - - val -}; - -fn main() { - println!("{}", BOO); -} diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr b/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr deleted file mode 100644 index 0ae9a40c96aaa..0000000000000 --- a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: rustc_peek: bit not set - --> $DIR/indirect-mutation-offset.rs:34:14 - | -LL | unsafe { rustc_peek(x) }; - | ^^^^^^^^^^^^^ - -error: stop_after_dataflow ended compilation - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/mir/mir_calls_to_shims.rs b/src/test/ui/mir/mir_calls_to_shims.rs index de8d958af45e3..6f13d5612ce51 100644 --- a/src/test/ui/mir/mir_calls_to_shims.rs +++ b/src/test/ui/mir/mir_calls_to_shims.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![feature(fn_traits)] #![feature(never_type)] diff --git a/src/test/ui/mir/mir_drop_order.rs b/src/test/ui/mir/mir_drop_order.rs index 2bc5cf1c97637..2949437b1e4b6 100644 --- a/src/test/ui/mir/mir_drop_order.rs +++ b/src/test/ui/mir/mir_drop_order.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default use std::cell::RefCell; use std::panic; diff --git a/src/test/ui/mismatched_types/abridged.rs b/src/test/ui/mismatched_types/abridged.rs index 9a5c183ca3428..41ab6d4c57844 100644 --- a/src/test/ui/mismatched_types/abridged.rs +++ b/src/test/ui/mismatched_types/abridged.rs @@ -50,13 +50,4 @@ fn e() -> X, String> { x //~ ERROR mismatched types } -fn f() -> String { - 1+2 //~ ERROR mismatched types -} - - -fn g() -> String { - -2 //~ ERROR mismatched types -} - fn main() {} diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index ded12d89c099d..b7f3b3dde8a93 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -66,34 +66,6 @@ LL | x = note: expected type `X, _>` found type `X, _>` -error[E0308]: mismatched types - --> $DIR/abridged.rs:54:5 - | -LL | fn f() -> String { - | ------ expected `std::string::String` because of return type -LL | 1+2 - | ^^^ - | | - | expected struct `std::string::String`, found integer - | help: try using a conversion method: `(1+2).to_string()` - | - = note: expected type `std::string::String` - found type `{integer}` - -error[E0308]: mismatched types - --> $DIR/abridged.rs:59:5 - | -LL | fn g() -> String { - | ------ expected `std::string::String` because of return type -LL | -2 - | ^^ - | | - | expected struct `std::string::String`, found integer - | help: try using a conversion method: `(-2).to_string()` - | - = note: expected type `std::string::String` - found type `{integer}` - -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/issue-36053-2.rs b/src/test/ui/mismatched_types/issue-36053-2.rs index 9035e3380b0c5..9edfebcd49471 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.rs +++ b/src/test/ui/mismatched_types/issue-36053-2.rs @@ -7,4 +7,5 @@ fn main() { once::<&str>("str").fuse().filter(|a: &str| true).count(); //~^ ERROR no method named `count` //~| ERROR type mismatch in closure arguments + //~| ERROR type mismatch in closure arguments } diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 72f3220cc1aba..89c7b0981158a 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -16,6 +16,14 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | | | expected signature of `for<'r> fn(&'r &str) -> _` -error: aborting due to 2 previous errors +error[E0631]: type mismatch in closure arguments + --> $DIR/issue-36053-2.rs:7:32 + | +LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); + | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _` + | | + | expected signature of `fn(&&str) -> _` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/mod/mod_file_disambig.stderr b/src/test/ui/mod/mod_file_disambig.stderr index 2b77d866fb30b..27df0241aa21f 100644 --- a/src/test/ui/mod/mod_file_disambig.stderr +++ b/src/test/ui/mod/mod_file_disambig.stderr @@ -8,4 +8,3 @@ LL | mod mod_file_disambig_aux; error: aborting due to previous error -For more information about this error, try `rustc --explain E0584`. diff --git a/src/test/ui/multiple-plugin-registrars.stderr b/src/test/ui/multiple-plugin-registrars.stderr index dad8172e0c59e..0e8379841f960 100644 --- a/src/test/ui/multiple-plugin-registrars.stderr +++ b/src/test/ui/multiple-plugin-registrars.stderr @@ -1,17 +1,3 @@ -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/multiple-plugin-registrars.rs:6:1 - | -LL | #[plugin_registrar] - | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - | - = note: `#[warn(deprecated)]` on by default - -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/multiple-plugin-registrars.rs:9:1 - | -LL | #[plugin_registrar] - | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - error: multiple plugin registration functions found | note: one is here diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index 77da07f40d536..aa21928aaeff2 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -37,9 +37,6 @@ LL | use namespace_mix::xm2::S; error[E0423]: expected value, found struct variant `m7::V` --> $DIR/namespace-mix.rs:100:11 | -LL | V {}, - | ---- `m7::V` defined here -... LL | check(m7::V); | ^^^^^ did you mean `m7::V { /* fields */ }`? help: a tuple variant with a similar name exists diff --git a/src/test/ui/never_type/never-assign-dead-code.rs b/src/test/ui/never-assign-dead-code.rs similarity index 82% rename from src/test/ui/never_type/never-assign-dead-code.rs rename to src/test/ui/never-assign-dead-code.rs index 7bb7c87097c50..fd5fbc30611a9 100644 --- a/src/test/ui/never_type/never-assign-dead-code.rs +++ b/src/test/ui/never-assign-dead-code.rs @@ -1,10 +1,10 @@ // Test that an assignment of type ! makes the rest of the block dead code. -// check-pass - #![feature(never_type)] +// build-pass (FIXME(62277): could be check-pass?) #![warn(unused)] + fn main() { let x: ! = panic!("aah"); //~ WARN unused drop(x); //~ WARN unreachable diff --git a/src/test/ui/never_type/never-assign-dead-code.stderr b/src/test/ui/never-assign-dead-code.stderr similarity index 92% rename from src/test/ui/never_type/never-assign-dead-code.stderr rename to src/test/ui/never-assign-dead-code.stderr index 1860150fa8bc6..b887d580e68a9 100644 --- a/src/test/ui/never_type/never-assign-dead-code.stderr +++ b/src/test/ui/never-assign-dead-code.stderr @@ -7,7 +7,7 @@ LL | drop(x); | ^^^^^^^^ unreachable statement | note: lint level defined here - --> $DIR/never-assign-dead-code.rs:6:9 + --> $DIR/never-assign-dead-code.rs:5:9 | LL | #![warn(unused)] | ^^^^^^ @@ -29,7 +29,7 @@ LL | let x: ! = panic!("aah"); | ^ help: consider prefixing with an underscore: `_x` | note: lint level defined here - --> $DIR/never-assign-dead-code.rs:6:9 + --> $DIR/never-assign-dead-code.rs:5:9 | LL | #![warn(unused)] | ^^^^^^ diff --git a/src/test/ui/never_type/never-assign-wrong-type.rs b/src/test/ui/never-assign-wrong-type.rs similarity index 100% rename from src/test/ui/never_type/never-assign-wrong-type.rs rename to src/test/ui/never-assign-wrong-type.rs diff --git a/src/test/ui/never_type/never-assign-wrong-type.stderr b/src/test/ui/never-assign-wrong-type.stderr similarity index 100% rename from src/test/ui/never_type/never-assign-wrong-type.stderr rename to src/test/ui/never-assign-wrong-type.stderr diff --git a/src/test/ui/never_type/never-from-impl-is-reserved.rs b/src/test/ui/never-from-impl-is-reserved.rs similarity index 100% rename from src/test/ui/never_type/never-from-impl-is-reserved.rs rename to src/test/ui/never-from-impl-is-reserved.rs diff --git a/src/test/ui/never_type/never-from-impl-is-reserved.stderr b/src/test/ui/never-from-impl-is-reserved.stderr similarity index 100% rename from src/test/ui/never_type/never-from-impl-is-reserved.stderr rename to src/test/ui/never-from-impl-is-reserved.stderr diff --git a/src/test/ui/never_type/never-result.rs b/src/test/ui/never-result.rs similarity index 99% rename from src/test/ui/never_type/never-result.rs rename to src/test/ui/never-result.rs index 35af37910ef3e..98ce326aa6631 100644 --- a/src/test/ui/never_type/never-result.rs +++ b/src/test/ui/never-result.rs @@ -2,7 +2,6 @@ #![allow(unused_variables)] #![allow(unreachable_code)] - // Test that we can extract a ! through pattern matching then use it as several different types. #![feature(never_type)] diff --git a/src/test/ui/never_type/never-type-rvalues.rs b/src/test/ui/never-type-rvalues.rs similarity index 100% rename from src/test/ui/never_type/never-type-rvalues.rs rename to src/test/ui/never-type-rvalues.rs diff --git a/src/test/ui/never_type/never_coercions.rs b/src/test/ui/never_coercions.rs similarity index 100% rename from src/test/ui/never_type/never_coercions.rs rename to src/test/ui/never_coercions.rs diff --git a/src/test/ui/never_type/never_transmute_never.rs b/src/test/ui/never_transmute_never.rs similarity index 87% rename from src/test/ui/never_type/never_transmute_never.rs rename to src/test/ui/never_transmute_never.rs index fce3ced9aac7f..5bad756b8762f 100644 --- a/src/test/ui/never_type/never_transmute_never.rs +++ b/src/test/ui/never_transmute_never.rs @@ -1,4 +1,4 @@ -// check-pass +// build-pass (FIXME(62277): could be check-pass?) #![crate_type="lib"] diff --git a/src/test/ui/nll/empty-type-predicate-2.rs b/src/test/ui/nll/empty-type-predicate-2.rs deleted file mode 100644 index 20d6e47f75300..0000000000000 --- a/src/test/ui/nll/empty-type-predicate-2.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Regression test for #65553 -// -// `D::Error:` is lowered to `D::Error: ReEmpty` - check that we don't ICE in -// NLL for the unexpected region. - -// check-pass - -trait Deserializer { - type Error; -} - -fn d1() where D::Error: {} - -fn d2() { - d1::(); -} - -fn main() {} diff --git a/src/test/ui/nll/empty-type-predicate.rs b/src/test/ui/nll/empty-type-predicate.rs index d126a455daeb2..48073f8749e75 100644 --- a/src/test/ui/nll/empty-type-predicate.rs +++ b/src/test/ui/nll/empty-type-predicate.rs @@ -3,9 +3,9 @@ // `dyn T:` is lowered to `dyn T: ReEmpty` - check that we don't ICE in NLL for // the unexpected region. -// check-pass +// build-pass (FIXME(62277): could be check-pass?) trait T {} fn f() where dyn T: {} -fn main() { f(); } +fn main() {} diff --git a/src/test/ui/nll/get_default.polonius.stderr b/src/test/ui/nll/get_default.polonius.stderr index 476d86cfba9c3..2df6d5d61fc46 100644 --- a/src/test/ui/nll/get_default.polonius.stderr +++ b/src/test/ui/nll/get_default.polonius.stderr @@ -1,9 +1,6 @@ error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable --> $DIR/get_default.rs:32:17 | -LL | fn err(map: &mut Map) -> &String { - | - let's call the lifetime of this reference `'1` -LL | loop { LL | match map.get() { | --- immutable borrow occurs here LL | Some(v) => { @@ -11,7 +8,7 @@ LL | map.set(String::new()); // Both AST and MIR error here | ^^^ mutable borrow occurs here LL | LL | return v; - | - returning this value requires that `*map` is borrowed for `'1` + | - immutable borrow later used here error: aborting due to previous error diff --git a/src/test/ui/nll/issue-50716.stderr b/src/test/ui/nll/issue-50716.stderr index 74c33df37a09e..b19e3a9dfb345 100644 --- a/src/test/ui/nll/issue-50716.stderr +++ b/src/test/ui/nll/issue-50716.stderr @@ -6,7 +6,7 @@ LL | let _x = *s; | = note: expected type `std::marker::Sized` found type `std::marker::Sized` -note: the lifetime `'a` as defined on the function body at 9:8... +note: the lifetime 'a as defined on the function body at 9:8... --> $DIR/issue-50716.rs:9:8 | LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) diff --git a/src/test/ui/nll/issue-52742.stderr b/src/test/ui/nll/issue-52742.stderr index 0cdc2d9443926..90a35177f4c3b 100644 --- a/src/test/ui/nll/issue-52742.stderr +++ b/src/test/ui/nll/issue-52742.stderr @@ -4,7 +4,7 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | self.y = b.z | ^^^ | -note: ...the reference is valid for the lifetime `'_` as defined on the impl at 12:10... +note: ...the reference is valid for the lifetime '_ as defined on the impl at 12:10... --> $DIR/issue-52742.rs:12:10 | LL | impl Foo<'_, '_> { diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr index 714a63b670c66..ffb94ed7dd7c0 100644 --- a/src/test/ui/nll/issue-55394.stderr +++ b/src/test/ui/nll/issue-55394.stderr @@ -16,7 +16,7 @@ note: ...so that reference does not outlive borrowed content | LL | Foo { bar } | ^^^ -note: but, the lifetime must be valid for the lifetime `'_` as defined on the impl at 7:10... +note: but, the lifetime must be valid for the lifetime '_ as defined on the impl at 7:10... --> $DIR/issue-55394.rs:7:10 | LL | impl Foo<'_> { @@ -27,4 +27,3 @@ LL | impl Foo<'_> { error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/nll/issue-55401.stderr b/src/test/ui/nll/issue-55401.stderr index 2dc7236cbc274..4ec16ba055a4c 100644 --- a/src/test/ui/nll/issue-55401.stderr +++ b/src/test/ui/nll/issue-55401.stderr @@ -5,7 +5,7 @@ LL | *y | ^^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 1:47 +note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 1:47 --> $DIR/issue-55401.rs:1:47 | LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { diff --git a/src/test/ui/nll/issue-63154-normalize.rs b/src/test/ui/nll/issue-63154-normalize.rs deleted file mode 100644 index 484c12879d33a..0000000000000 --- a/src/test/ui/nll/issue-63154-normalize.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Regression test for rust-lang/rust#63154 -// -// Before, we would ICE after failing to normalize the destination type -// when checking call destinations and also when checking MIR -// assignment statements. - -// check-pass - -trait HasAssocType { - type Inner; -} - -impl HasAssocType for () { - type Inner = (); -} - -trait Tr: Fn(I) -> Option {} -impl Option> Tr for Q {} - -fn f() -> impl Tr { - |_| None -} - -fn g(f: impl Tr) -> impl Tr { - f -} - -fn h() { - g(f())(()); -} - -fn main() { - h(); -} diff --git a/src/test/ui/nll/loan_ends_mid_block_pair.polonius.stderr b/src/test/ui/nll/loan_ends_mid_block_pair.polonius.stderr new file mode 100644 index 0000000000000..eb8442b31d7c7 --- /dev/null +++ b/src/test/ui/nll/loan_ends_mid_block_pair.polonius.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `data.0` because it is borrowed + --> $DIR/loan_ends_mid_block_pair.rs:12:5 + | +LL | let c = &mut data.0; + | ----------- borrow of `data.0` occurs here +LL | capitalize(c); +LL | data.0 = 'e'; + | ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here +... +LL | capitalize(c); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr index 3a152fbc6fce8..951e73e7fd765 100644 --- a/src/test/ui/nll/normalization-bounds-error.stderr +++ b/src/test/ui/nll/normalization-bounds-error.stderr @@ -4,12 +4,12 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` d LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'d` as defined on the function body at 12:14... +note: first, the lifetime cannot outlive the lifetime 'd as defined on the function body at 12:14... --> $DIR/normalization-bounds-error.rs:12:14 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} | ^^ -note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the function body at 12:18... +note: ...but the lifetime must also be valid for the lifetime 'a as defined on the function body at 12:18... --> $DIR/normalization-bounds-error.rs:12:18 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} @@ -20,4 +20,3 @@ LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/nll/polonius/polonius-smoke-test.stderr b/src/test/ui/nll/polonius/polonius-smoke-test.stderr index 1faf8e2212aab..dbc5b7a019a69 100644 --- a/src/test/ui/nll/polonius/polonius-smoke-test.stderr +++ b/src/test/ui/nll/polonius/polonius-smoke-test.stderr @@ -17,14 +17,12 @@ LL | let w = y; error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/polonius-smoke-test.rs:19:13 | -LL | pub fn use_while_mut_fr(x: &mut i32) -> &mut i32 { - | - let's call the lifetime of this reference `'1` LL | let y = &mut *x; | ------- borrow of `*x` occurs here LL | let z = x; | ^ move out of `x` occurs here LL | y - | - returning this value requires that `*x` is borrowed for `'1` + | - borrow later used here error[E0505]: cannot move out of `s` because it is borrowed --> $DIR/polonius-smoke-test.rs:43:5 diff --git a/src/test/ui/nll/promoted-liveness.rs b/src/test/ui/nll/promoted-liveness.rs deleted file mode 100644 index e5a8e1e5c2fcc..0000000000000 --- a/src/test/ui/nll/promoted-liveness.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Test that promoted that have larger mir bodies than their containing function -// don't cause an ICE. - -// check-pass - -fn main() { - &["0", "1", "2", "3", "4", "5", "6", "7"]; -} diff --git a/src/test/ui/nll/relate_tys/fn-subtype.rs b/src/test/ui/nll/relate_tys/fn-subtype.rs deleted file mode 100644 index ac00627ad00eb..0000000000000 --- a/src/test/ui/nll/relate_tys/fn-subtype.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Test that NLL produces correct spans for higher-ranked subtyping errors. -// -// compile-flags:-Zno-leak-check - -#![feature(nll)] - -fn main() { - let x: fn(&'static ()) = |_| {}; - let y: for<'a> fn(&'a ()) = x; //~ ERROR higher-ranked subtype error -} diff --git a/src/test/ui/nll/relate_tys/fn-subtype.stderr b/src/test/ui/nll/relate_tys/fn-subtype.stderr deleted file mode 100644 index b089b5aaa2535..0000000000000 --- a/src/test/ui/nll/relate_tys/fn-subtype.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: higher-ranked subtype error - --> $DIR/fn-subtype.rs:9:33 - | -LL | let y: for<'a> fn(&'a ()) = x; - | ^ - -error: aborting due to previous error - diff --git a/src/test/ui/nll/relate_tys/trait-hrtb.rs b/src/test/ui/nll/relate_tys/trait-hrtb.rs deleted file mode 100644 index 80f31ca6b4782..0000000000000 --- a/src/test/ui/nll/relate_tys/trait-hrtb.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Test that NLL generates proper error spans for trait HRTB errors -// -// compile-flags:-Zno-leak-check - -#![feature(nll)] - -trait Foo<'a> {} - -fn make_foo<'a>() -> Box> { - panic!() -} - -fn main() { - let x: Box> = make_foo(); - let y: Box Foo<'a>> = x; //~ ERROR higher-ranked subtype error -} diff --git a/src/test/ui/nll/relate_tys/trait-hrtb.stderr b/src/test/ui/nll/relate_tys/trait-hrtb.stderr deleted file mode 100644 index 4df2f352522a3..0000000000000 --- a/src/test/ui/nll/relate_tys/trait-hrtb.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: higher-ranked subtype error - --> $DIR/trait-hrtb.rs:15:39 - | -LL | let y: Box Foo<'a>> = x; - | ^ - -error: aborting due to previous error - diff --git a/src/test/ui/nll/return-ref-mut-issue-46557.polonius.stderr b/src/test/ui/nll/return-ref-mut-issue-46557.polonius.stderr new file mode 100644 index 0000000000000..8e3cf59cffb44 --- /dev/null +++ b/src/test/ui/nll/return-ref-mut-issue-46557.polonius.stderr @@ -0,0 +1,15 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/return-ref-mut-issue-46557.rs:4:21 + | +LL | let ref mut x = 1234543; + | ^^^^^^^ creates a temporary which is freed while still in use +LL | x + | - borrow later used here +LL | } + | - temporary value is freed at the end of this statement + | + = 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/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr index ecf9748af9ea3..f39f668e2329a 100644 --- a/src/test/ui/nll/trait-associated-constant.stderr +++ b/src/test/ui/nll/trait-associated-constant.stderr @@ -6,12 +6,12 @@ LL | const AC: Option<&'c str> = None; | = note: expected type `std::option::Option<&'b str>` found type `std::option::Option<&'c str>` -note: the lifetime `'c` as defined on the impl at 20:18... +note: the lifetime 'c as defined on the impl at 20:18... --> $DIR/trait-associated-constant.rs:20:18 | LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 20:14 +note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 20:14 --> $DIR/trait-associated-constant.rs:20:14 | LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr index 6986389af8814..00d58d34362e6 100644 --- a/src/test/ui/nll/type-alias-free-regions.stderr +++ b/src/test/ui/nll/type-alias-free-regions.stderr @@ -14,7 +14,7 @@ LL | | } = note: ...so that the expression is assignable: expected std::boxed::Box> found std::boxed::Box> -note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6... +note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 15:6... --> $DIR/type-alias-free-regions.rs:15:6 | LL | impl<'a> FromBox<'a> for C<'a> { @@ -39,7 +39,7 @@ LL | | } = note: ...so that the expression is assignable: expected std::boxed::Box<&isize> found std::boxed::Box<&isize> -note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 25:6... +note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 25:6... --> $DIR/type-alias-free-regions.rs:25:6 | LL | impl<'a> FromTuple<'a> for C<'a> { @@ -50,4 +50,3 @@ LL | impl<'a> FromTuple<'a> for C<'a> { error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr index 4ebd991078864..77e1339dc161d 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | >::C | ^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 7:8... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 7:8... --> $DIR/constant-in-expr-inherent-1.rs:7:8 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { @@ -21,4 +21,3 @@ LL | >::C error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. 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 4c7adf75d2fd7..0a8ad4221c986 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 @@ -5,7 +5,7 @@ LL | <() as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 17:8 +note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 17:8 --> $DIR/constant-in-expr-normalize.rs:17:8 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { 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 d01d022cba796..d596aaf098f77 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 @@ -5,7 +5,7 @@ LL | <() as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 9:8 +note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 9:8 --> $DIR/constant-in-expr-trait-item-1.rs:9:8 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { 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 dd294280b903a..80ff9a043d4d5 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 @@ -5,7 +5,7 @@ LL | >::C | ^^^^^^^^^^^^^^^^^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 9:8 +note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 9:8 --> $DIR/constant-in-expr-trait-item-2.rs:9:8 | LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr index d61659e7e9afc..77655fe091b62 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | T::C | ^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:8... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:8... --> $DIR/constant-in-expr-trait-item-3.rs:9:8 | LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { @@ -21,4 +21,3 @@ LL | T::C error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/no-patterns-in-args-macro.stderr b/src/test/ui/no-patterns-in-args-macro.stderr index f21df68d5a2cc..680430a05ee8a 100644 --- a/src/test/ui/no-patterns-in-args-macro.stderr +++ b/src/test/ui/no-patterns-in-args-macro.stderr @@ -18,5 +18,5 @@ LL | m!((bad, pat)); error: aborting due to 3 previous errors -Some errors have detailed explanations: E0130, E0561, E0642. +Some errors have detailed explanations: E0130, E0642. For more information about an error, try `rustc --explain E0130`. diff --git a/src/test/ui/no-patterns-in-args.stderr b/src/test/ui/no-patterns-in-args.stderr index 1c2ce86646787..b65e0ecd253e6 100644 --- a/src/test/ui/no-patterns-in-args.stderr +++ b/src/test/ui/no-patterns-in-args.stderr @@ -30,5 +30,4 @@ LL | type A2 = fn(&arg: u8); error: aborting due to 5 previous errors -Some errors have detailed explanations: E0130, E0561. -For more information about an error, try `rustc --explain E0130`. +For more information about this error, try `rustc --explain E0130`. diff --git a/src/test/ui/not-panic/not-panic-safe.stderr b/src/test/ui/not-panic/not-panic-safe.stderr index 2362ccd32de99..aa18b923044c6 100644 --- a/src/test/ui/not-panic/not-panic-safe.stderr +++ b/src/test/ui/not-panic/not-panic-safe.stderr @@ -8,7 +8,6 @@ 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: `std::panic::UnwindSafe` is implemented for `&i32`, but not for `&mut i32` error: aborting due to previous error diff --git a/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs b/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs index ced3c61ec162a..d210abdf499d0 100644 --- a/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs +++ b/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs @@ -1,4 +1,5 @@ // run-pass +// ignore-emscripten no i128 support #![deny(const_err)] diff --git a/src/test/ui/numbers-arithmetic/i128.rs b/src/test/ui/numbers-arithmetic/i128.rs index ef558c0aa0c02..ea0ef95e4f1af 100644 --- a/src/test/ui/numbers-arithmetic/i128.rs +++ b/src/test/ui/numbers-arithmetic/i128.rs @@ -1,6 +1,9 @@ // run-pass #![allow(overflowing_literals)] +// ignore-emscripten i128 doesn't work + + #![feature(test)] extern crate test; diff --git a/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs index c1959866e5c25..e9927304f23f8 100644 --- a/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs +++ b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs @@ -1,6 +1,6 @@ // run-pass // compile-flags: -C debug_assertions=yes -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // ignore-emscripten dies with an LLVM error use std::panic; diff --git a/src/test/ui/numbers-arithmetic/u128-as-f32.rs b/src/test/ui/numbers-arithmetic/u128-as-f32.rs index 2671a267f4a87..bef7deb62760e 100644 --- a/src/test/ui/numbers-arithmetic/u128-as-f32.rs +++ b/src/test/ui/numbers-arithmetic/u128-as-f32.rs @@ -1,4 +1,5 @@ // run-pass +// ignore-emscripten u128 not supported #![feature(test)] #![deny(overflowing_literals)] diff --git a/src/test/ui/numbers-arithmetic/u128.rs b/src/test/ui/numbers-arithmetic/u128.rs index 0b2305c6e8b1a..9394071632377 100644 --- a/src/test/ui/numbers-arithmetic/u128.rs +++ b/src/test/ui/numbers-arithmetic/u128.rs @@ -1,4 +1,6 @@ // run-pass +// ignore-emscripten u128 not supported + #![feature(test)] diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr index d66322c48ec98..2cdd6c5d890f2 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to LL | ss | ^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 54:10... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 54:10... --> $DIR/object-lifetime-default-elision.rs:54:10 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | ss | ^^ -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 54:13... +note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 54:13... --> $DIR/object-lifetime-default-elision.rs:54:13 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { @@ -29,7 +29,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | ss | ^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 54:10... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 54:10... --> $DIR/object-lifetime-default-elision.rs:54:10 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { @@ -39,7 +39,7 @@ note: ...so that the declared lifetime parameter bounds are satisfied | LL | ss | ^^ -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 54:13... +note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 54:13... --> $DIR/object-lifetime-default-elision.rs:54:13 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { @@ -50,4 +50,3 @@ LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr index 99f0ce0602b11..4f9cef12c5ef2 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr @@ -6,7 +6,7 @@ LL | ss.t = t; | = note: expected type `&'a std::boxed::Box<(dyn Test + 'static)>` found type `&'a std::boxed::Box<(dyn Test + 'a)>` -note: the lifetime `'a` as defined on the function body at 14:6... +note: the lifetime 'a as defined on the function body at 14:6... --> $DIR/object-lifetime-default-from-rptr-box-error.rs:14:6 | LL | fn c<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr index 07d4d8c8ed40b..3b7faee68aaba 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr @@ -6,7 +6,7 @@ LL | ss.t = t; | = note: expected type `&'a MyBox<(dyn Test + 'static)>` found type `&'a MyBox<(dyn Test + 'a)>` -note: the lifetime `'a` as defined on the function body at 20:6... +note: the lifetime 'a as defined on the function body at 20:6... --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:20:6 | LL | fn c<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr b/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr index f825475b96b03..928b920198232 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr @@ -18,7 +18,7 @@ LL | load0(ss) | = note: expected type `&MyBox<(dyn SomeTrait + 'static)>` found type `&MyBox<(dyn SomeTrait + 'a)>` -note: the lifetime `'a` as defined on the function body at 30:10... +note: the lifetime 'a as defined on the function body at 30:10... --> $DIR/object-lifetime-default-mybox.rs:30:10 | LL | fn load2<'a>(ss: &MyBox) -> MyBox { diff --git a/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr deleted file mode 100644 index 20993a680ba48..0000000000000 --- a/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:14:5 - | -LL | const X: usize; - | - the trait cannot contain associated consts like `X` -... -LL | t - | ^ the trait `Bar` cannot be made into an object - | - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T` - = note: required by cast to type `&dyn Bar` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-associated-consts.rs b/src/test/ui/object-safety/object-safety-associated-consts.rs index e1a772e5ab2f3..5900019ea915a 100644 --- a/src/test/ui/object-safety/object-safety-associated-consts.rs +++ b/src/test/ui/object-safety/object-safety-associated-consts.rs @@ -1,18 +1,14 @@ // Check that we correctly prevent users from making trait objects // from traits with associated consts. -// -// revisions: curr object_safe_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] trait Bar { const X: usize; } fn make_bar(t: &T) -> &dyn Bar { - //[curr]~^ ERROR E0038 + //~^ ERROR E0038 t - //[object_safe_for_dispatch]~^ ERROR E0038 } fn main() { diff --git a/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr b/src/test/ui/object-safety/object-safety-associated-consts.stderr similarity index 88% rename from src/test/ui/object-safety/object-safety-associated-consts.curr.stderr rename to src/test/ui/object-safety/object-safety-associated-consts.stderr index 67ef7a62f1052..7d5aa00356e0b 100644 --- a/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr +++ b/src/test/ui/object-safety/object-safety-associated-consts.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:12:1 + --> $DIR/object-safety-associated-consts.rs:9:1 | LL | const X: usize; | - the trait cannot contain associated consts like `X` diff --git a/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr deleted file mode 100644 index d3d8d36888836..0000000000000 --- a/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:20:5 - | -LL | fn bar(&self, t: T); - | --- method `bar` has generic type parameters -... -LL | t - | ^ the trait `Bar` cannot be made into an object - | - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T` - = note: required by cast to type `&dyn Bar` - -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:26:5 - | -LL | fn bar(&self, t: T); - | --- method `bar` has generic type parameters -... -LL | t as &dyn Bar - | ^ the trait `Bar` cannot be made into an object - | - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T` - = note: required by cast to type `&dyn Bar` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-generics.rs b/src/test/ui/object-safety/object-safety-generics.rs index 63dcd169925e4..d63ea28c8f227 100644 --- a/src/test/ui/object-safety/object-safety-generics.rs +++ b/src/test/ui/object-safety/object-safety-generics.rs @@ -1,10 +1,6 @@ // Check that we correctly prevent users from making trait objects // from traits with generic methods, unless `where Self : Sized` is // present. -// revisions: curr object_safe_for_dispatch - -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] - trait Bar { fn bar(&self, t: T); @@ -16,15 +12,13 @@ trait Quux { } fn make_bar(t: &T) -> &dyn Bar { - //[curr]~^ ERROR E0038 + //~^ ERROR E0038 t - //[object_safe_for_dispatch]~^ ERROR E0038 } fn make_bar_explicit(t: &T) -> &dyn Bar { - //[curr]~^ ERROR E0038 + //~^ ERROR E0038 t as &dyn Bar - //[object_safe_for_dispatch]~^ ERROR E0038 } fn make_quux(t: &T) -> &dyn Quux { diff --git a/src/test/ui/object-safety/object-safety-generics.curr.stderr b/src/test/ui/object-safety/object-safety-generics.stderr similarity index 89% rename from src/test/ui/object-safety/object-safety-generics.curr.stderr rename to src/test/ui/object-safety/object-safety-generics.stderr index 8ae9236a5c322..b25e0052e4163 100644 --- a/src/test/ui/object-safety/object-safety-generics.curr.stderr +++ b/src/test/ui/object-safety/object-safety-generics.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:18:1 + --> $DIR/object-safety-generics.rs:14:1 | LL | fn bar(&self, t: T); | --- method `bar` has generic type parameters @@ -8,7 +8,7 @@ LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:24:1 + --> $DIR/object-safety-generics.rs:19:1 | LL | fn bar(&self, t: T); | --- method `bar` has generic type parameters diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr deleted file mode 100644 index 03b2b8da07533..0000000000000 --- a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:24:5 - | -LL | fn bar(&self, x: &Self); - | --- method `bar` references the `Self` type in its parameters or return type -... -LL | t - | ^ the trait `Bar` cannot be made into an object - | - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T` - = note: required by cast to type `&dyn Bar` - -error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:30:5 - | -LL | fn baz(&self) -> Self; - | --- method `baz` references the `Self` type in its parameters or return type -... -LL | t - | ^ the trait `Baz` cannot be made into an object - | - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Baz>` for `&T` - = note: required by cast to type `&dyn Baz` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.rs b/src/test/ui/object-safety/object-safety-mentions-Self.rs index 412d16ff3c7ce..f13ffe5362670 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.rs +++ b/src/test/ui/object-safety/object-safety-mentions-Self.rs @@ -1,34 +1,27 @@ // Check that we correctly prevent users from making trait objects // form traits that make use of `Self` in an argument or return // position, unless `where Self : Sized` is present.. -// -// revisions: curr object_safe_for_dispatch - -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] - trait Bar { fn bar(&self, x: &Self); } trait Baz { - fn baz(&self) -> Self; + fn bar(&self) -> Self; } trait Quux { - fn quux(&self, s: &Self) -> Self where Self : Sized; + fn get(&self, s: &Self) -> Self where Self : Sized; } fn make_bar(t: &T) -> &dyn Bar { - //[curr]~^ ERROR E0038 - t - //[object_safe_for_dispatch]~^ ERROR E0038 + //~^ ERROR E0038 + loop { } } fn make_baz(t: &T) -> &dyn Baz { - //[curr]~^ ERROR E0038 + //~^ ERROR E0038 t - //[object_safe_for_dispatch]~^ ERROR E0038 } fn make_quux(t: &T) -> &dyn Quux { @@ -39,4 +32,5 @@ fn make_quux_explicit(t: &T) -> &dyn Quux { t as &dyn Quux } -fn main() {} +fn main() { +} diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.stderr similarity index 83% rename from src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr rename to src/test/ui/object-safety/object-safety-mentions-Self.stderr index 297cd876187fe..971e79cb0210f 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr +++ b/src/test/ui/object-safety/object-safety-mentions-Self.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:22:1 + --> $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 @@ -8,10 +8,10 @@ LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:28:1 + --> $DIR/object-safety-mentions-Self.rs:22:1 | -LL | fn baz(&self) -> Self; - | --- method `baz` references the `Self` type in its parameters or return type +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 diff --git a/src/test/ui/object-safety/object-safety-no-static.curr.stderr b/src/test/ui/object-safety/object-safety-no-static.curr.stderr deleted file mode 100644 index 1641ce577719e..0000000000000 --- a/src/test/ui/object-safety/object-safety-no-static.curr.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:12:1 - | -LL | fn foo() {} - | --- associated function `foo` has no `self` parameter -... -LL | fn diverges() -> Box { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr deleted file mode 100644 index 91a9285b63ccc..0000000000000 --- a/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:22:27 - | -LL | fn foo() {} - | --- associated function `foo` has no `self` parameter -... -LL | let b: Box = Box::new(Bar); - | ^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object - | - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box` - = note: required by cast to type `std::boxed::Box` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-no-static.rs b/src/test/ui/object-safety/object-safety-no-static.rs index 03b6221748388..55d31ce808769 100644 --- a/src/test/ui/object-safety/object-safety-no-static.rs +++ b/src/test/ui/object-safety/object-safety-no-static.rs @@ -1,24 +1,14 @@ // Check that we correctly prevent users from making trait objects // from traits with static methods. -// -// revisions: curr object_safe_for_dispatch - -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] trait Foo { - fn foo() {} + fn foo(); } -fn diverges() -> Box { - //[curr]~^ ERROR E0038 +fn foo_implicit(b: Box) -> Box { + //~^ ERROR E0038 loop { } } -struct Bar; - -impl Foo for Bar {} - fn main() { - let b: Box = Box::new(Bar); - //[object_safe_for_dispatch]~^ ERROR E0038 } diff --git a/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr deleted file mode 100644 index 06ecfd019c841..0000000000000 --- a/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:16:5 - | -LL | t - | ^ the trait `Bar` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T` - = note: required by cast to type `&dyn Bar` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-sized-2.rs b/src/test/ui/object-safety/object-safety-sized-2.rs index 1e79b8cd917c7..7235b22404e29 100644 --- a/src/test/ui/object-safety/object-safety-sized-2.rs +++ b/src/test/ui/object-safety/object-safety-sized-2.rs @@ -1,9 +1,5 @@ // Check that we correctly prevent users from making trait objects // from traits where `Self : Sized`. -// -// revisions: curr object_safe_for_dispatch - -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] trait Bar where Self : Sized @@ -12,9 +8,8 @@ trait Bar } fn make_bar(t: &T) -> &dyn Bar { - //[curr]~^ ERROR E0038 - t - //[object_safe_for_dispatch]~^ ERROR E0038 + //~^ ERROR E0038 + loop { } } fn main() { diff --git a/src/test/ui/object-safety/object-safety-sized-2.curr.stderr b/src/test/ui/object-safety/object-safety-sized-2.stderr similarity index 89% rename from src/test/ui/object-safety/object-safety-sized-2.curr.stderr rename to src/test/ui/object-safety/object-safety-sized-2.stderr index 1e1d2bf64c427..dcaf2ff0bc294 100644 --- a/src/test/ui/object-safety/object-safety-sized-2.curr.stderr +++ b/src/test/ui/object-safety/object-safety-sized-2.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:14:1 + --> $DIR/object-safety-sized-2.rs:10:1 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object diff --git a/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr deleted file mode 100644 index 3d88dfc40ed38..0000000000000 --- a/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:14:5 - | -LL | t - | ^ the trait `Bar` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T` - = note: required by cast to type `&dyn Bar` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-sized.rs b/src/test/ui/object-safety/object-safety-sized.rs index b424b892d3b45..1312bb34717ee 100644 --- a/src/test/ui/object-safety/object-safety-sized.rs +++ b/src/test/ui/object-safety/object-safety-sized.rs @@ -1,18 +1,13 @@ // Check that we correctly prevent users from making trait objects // from traits where `Self : Sized`. -// -// revisions: curr object_safe_for_dispatch - -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] trait Bar : Sized { fn bar(&self, t: T); } fn make_bar(t: &T) -> &dyn Bar { - //[curr]~^ ERROR E0038 + //~^ ERROR E0038 t - //[object_safe_for_dispatch]~^ ERROR E0038 } fn main() { diff --git a/src/test/ui/object-safety/object-safety-sized.curr.stderr b/src/test/ui/object-safety/object-safety-sized.stderr similarity index 90% rename from src/test/ui/object-safety/object-safety-sized.curr.stderr rename to src/test/ui/object-safety/object-safety-sized.stderr index 1a67e79e83d32..98bc73e38d4cc 100644 --- a/src/test/ui/object-safety/object-safety-sized.curr.stderr +++ b/src/test/ui/object-safety/object-safety-sized.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:12:1 + --> $DIR/object-safety-sized.rs:8:1 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object diff --git a/src/test/ui/occurs-check-2.stderr b/src/test/ui/occurs-check-2.stderr index 7f93697c6f7a7..74e29a5aea728 100644 --- a/src/test/ui/occurs-check-2.stderr +++ b/src/test/ui/occurs-check-2.stderr @@ -5,7 +5,7 @@ LL | f = box g; | ^^^^^ | | | cyclic type of infinite size - | help: try using a conversion method: `(box g).to_string()` + | help: try using a conversion method: `box g.to_string()` error: aborting due to previous error diff --git a/src/test/ui/occurs-check.stderr b/src/test/ui/occurs-check.stderr index 01e2b1f774910..61ce61b1cbeb6 100644 --- a/src/test/ui/occurs-check.stderr +++ b/src/test/ui/occurs-check.stderr @@ -5,7 +5,7 @@ LL | f = box f; | ^^^^^ | | | cyclic type of infinite size - | help: try using a conversion method: `(box f).to_string()` + | help: try using a conversion method: `box f.to_string()` error: aborting due to previous error diff --git a/src/test/ui/or-patterns/issue-64879-trailing-before-guard.rs b/src/test/ui/or-patterns/issue-64879-trailing-before-guard.rs deleted file mode 100644 index 181c770096a5f..0000000000000 --- a/src/test/ui/or-patterns/issue-64879-trailing-before-guard.rs +++ /dev/null @@ -1,15 +0,0 @@ -// In this regression test we check that a trailing `|` in an or-pattern just -// before the `if` token of a `match` guard will receive parser recovery with -// an appropriate error message. - -enum E { A, B } - -fn main() { - match E::A { - E::A | - E::B | //~ ERROR a trailing `|` is not allowed in an or-pattern - if true => { - let recovery_witness: bool = 0; //~ ERROR mismatched types - } - } -} diff --git a/src/test/ui/or-patterns/issue-64879-trailing-before-guard.stderr b/src/test/ui/or-patterns/issue-64879-trailing-before-guard.stderr deleted file mode 100644 index db6670fc5b1e0..0000000000000 --- a/src/test/ui/or-patterns/issue-64879-trailing-before-guard.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/issue-64879-trailing-before-guard.rs:10:14 - | -LL | E::A | - | ---- while parsing this or-pattern starting here -LL | E::B | - | ^ help: remove the `|` - -error[E0308]: mismatched types - --> $DIR/issue-64879-trailing-before-guard.rs:12:42 - | -LL | let recovery_witness: bool = 0; - | ^ expected bool, found integer - | - = note: expected type `bool` - found type `{integer}` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/or-patterns/multiple-pattern-typo.stderr b/src/test/ui/or-patterns/multiple-pattern-typo.stderr index c71c760b1e303..c61b5cb208251 100644 --- a/src/test/ui/or-patterns/multiple-pattern-typo.stderr +++ b/src/test/ui/or-patterns/multiple-pattern-typo.stderr @@ -2,49 +2,37 @@ 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: `|` - | | - | while parsing this or-pattern starting here + | ^^ 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: `|` - | | - | while parsing this or-pattern starting here + | ^^ 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: `|` - | | - | while parsing this or-pattern starting here + | ^^ 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: `|` - | | - | while parsing this or-pattern starting here + | ^^ 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: `|` - | | - | while parsing this or-pattern starting here + | ^^ 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: `|` - | | - | while parsing this or-pattern starting here + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` error: unexpected token `||` after pattern --> $DIR/multiple-pattern-typo.rs:42:9 diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr index 6d08b47c058ed..2a3a6abfb7b62 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -51,32 +51,24 @@ error: a leading `|` is only allowed in a top-level pattern | LL | let ( || A | B) = E::A; | ^^ help: remove the `||` - | - = note: alternatives in or-patterns are separated with `|`, not `||` 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 `||` - | - = note: alternatives in or-patterns are separated with `|`, not `||` 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 `||` - | - = note: alternatives in or-patterns are separated with `|`, not `||` 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 `||` - | - = note: alternatives in or-patterns are separated with `|`, not `||` error: no rules expected the token `|` --> $DIR/or-patterns-syntactic-fail.rs:14:15 diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs index 9667711242ce6..5fe72caf9c1ff 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs +++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs @@ -4,7 +4,6 @@ // check-pass #![feature(or_patterns)] -#![feature(box_patterns)] fn main() {} diff --git a/src/test/ui/or-patterns/remove-leading-vert.fixed b/src/test/ui/or-patterns/remove-leading-vert.fixed index 443ef398293d9..e96d76061ac28 100644 --- a/src/test/ui/or-patterns/remove-leading-vert.fixed +++ b/src/test/ui/or-patterns/remove-leading-vert.fixed @@ -1,4 +1,4 @@ -// Test the suggestion to remove a leading, or trailing `|`. +// Test the suggestion to remove a leading `|`. // run-rustfix @@ -8,7 +8,7 @@ fn main() {} #[cfg(FALSE)] -fn leading() { +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 @@ -21,26 +21,3 @@ fn leading() { 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 } - -#[cfg(FALSE)] -fn trailing() { - let ( A ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern - let (a ,): (E,); //~ ERROR a trailing `|` is not allowed in an or-pattern - let ( A | B ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern - let [ A | B ]: [E; 1]; //~ ERROR a trailing `|` is not allowed in an or-pattern - let S { f: B }; //~ ERROR a trailing `|` is not allowed in an or-pattern - let ( A | B ): E; //~ ERROR unexpected token `||` after pattern - //~^ ERROR a trailing `|` is not allowed in an or-pattern - match A { - A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern - A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern - A | B => {} //~ ERROR unexpected token `||` after pattern - //~^ ERROR a trailing `|` is not allowed in an or-pattern - | A | B => {} - //~^ ERROR a trailing `|` is not allowed in an or-pattern - } - - let a : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern - let a = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern - let a ; //~ ERROR a trailing `|` is not allowed in an or-pattern -} diff --git a/src/test/ui/or-patterns/remove-leading-vert.rs b/src/test/ui/or-patterns/remove-leading-vert.rs index 3c427a6f7b23e..3790b17553fe3 100644 --- a/src/test/ui/or-patterns/remove-leading-vert.rs +++ b/src/test/ui/or-patterns/remove-leading-vert.rs @@ -1,4 +1,4 @@ -// Test the suggestion to remove a leading, or trailing `|`. +// Test the suggestion to remove a leading `|`. // run-rustfix @@ -8,7 +8,7 @@ fn main() {} #[cfg(FALSE)] -fn leading() { +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 @@ -21,26 +21,3 @@ fn leading() { 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 } - -#[cfg(FALSE)] -fn trailing() { - let ( A | ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern - let (a |,): (E,); //~ ERROR a trailing `|` is not allowed in an or-pattern - let ( A | B | ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern - let [ A | B | ]: [E; 1]; //~ ERROR a trailing `|` is not allowed in an or-pattern - let S { f: B | }; //~ ERROR a trailing `|` is not allowed in an or-pattern - let ( A || B | ): E; //~ ERROR unexpected token `||` after pattern - //~^ ERROR a trailing `|` is not allowed in an or-pattern - match A { - A | => {} //~ ERROR a trailing `|` is not allowed in an or-pattern - A || => {} //~ ERROR a trailing `|` is not allowed in an or-pattern - A || B | => {} //~ ERROR unexpected token `||` after pattern - //~^ ERROR a trailing `|` is not allowed in an or-pattern - | A | B | => {} - //~^ ERROR a trailing `|` is not allowed in an or-pattern - } - - let a | : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern - let a | = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern - let a | ; //~ ERROR a trailing `|` is not allowed in an or-pattern -} diff --git a/src/test/ui/or-patterns/remove-leading-vert.stderr b/src/test/ui/or-patterns/remove-leading-vert.stderr index 53025230a63c2..cbe06f997296a 100644 --- a/src/test/ui/or-patterns/remove-leading-vert.stderr +++ b/src/test/ui/or-patterns/remove-leading-vert.stderr @@ -9,8 +9,6 @@ error: a leading `|` is not allowed in a parameter pattern | LL | fn fun2( || A: E) {} | ^^ help: remove the `||` - | - = note: alternatives in or-patterns are separated with `|`, not `||` error: a leading `|` is only allowed in a top-level pattern --> $DIR/remove-leading-vert.rs:14:11 @@ -23,8 +21,6 @@ error: a leading `|` is only allowed in a top-level pattern | LL | let ( || A): (E); | ^^ help: remove the `||` - | - = note: alternatives in or-patterns are separated with `|`, not `||` error: a leading `|` is only allowed in a top-level pattern --> $DIR/remove-leading-vert.rs:16:11 @@ -43,8 +39,6 @@ error: a leading `|` is only allowed in a top-level pattern | LL | let [ || A ]: [E; 1]; | ^^ help: remove the `||` - | - = note: alternatives in or-patterns are separated with `|`, not `||` error: a leading `|` is only allowed in a top-level pattern --> $DIR/remove-leading-vert.rs:19:13 @@ -57,8 +51,6 @@ error: a leading `|` is only allowed in a top-level pattern | LL | let TS( || A ): TS; | ^^ help: remove the `||` - | - = note: alternatives in or-patterns are separated with `|`, not `||` error: a leading `|` is only allowed in a top-level pattern --> $DIR/remove-leading-vert.rs:21:17 @@ -71,130 +63,6 @@ error: a leading `|` is only allowed in a top-level pattern | LL | let NS { f: || A }: NS; | ^^ help: remove the `||` - | - = note: alternatives in or-patterns are separated with `|`, not `||` - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:27:13 - | -LL | let ( A | ): E; - | - ^ help: remove the `|` - | | - | while parsing this or-pattern starting here - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:28:12 - | -LL | let (a |,): (E,); - | - ^ help: remove the `|` - | | - | while parsing this or-pattern starting here - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:29:17 - | -LL | let ( A | B | ): E; - | - ^ help: remove the `|` - | | - | while parsing this or-pattern starting here - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:30:17 - | -LL | let [ A | B | ]: [E; 1]; - | - ^ help: remove the `|` - | | - | while parsing this or-pattern starting here - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:31:18 - | -LL | let S { f: B | }; - | - ^ help: remove the `|` - | | - | while parsing this or-pattern starting here - -error: unexpected token `||` after pattern - --> $DIR/remove-leading-vert.rs:32:13 - | -LL | let ( A || B | ): E; - | - ^^ help: use a single `|` to separate multiple alternative patterns: `|` - | | - | while parsing this or-pattern starting here - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:32:18 - | -LL | let ( A || B | ): E; - | - ^ help: remove the `|` - | | - | while parsing this or-pattern starting here - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:35:11 - | -LL | A | => {} - | - ^ help: remove the `|` - | | - | while parsing this or-pattern starting here - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:36:11 - | -LL | A || => {} - | - ^^ help: remove the `||` - | | - | while parsing this or-pattern starting here - | - = note: alternatives in or-patterns are separated with `|`, not `||` - -error: unexpected token `||` after pattern - --> $DIR/remove-leading-vert.rs:37:11 - | -LL | A || B | => {} - | - ^^ help: use a single `|` to separate multiple alternative patterns: `|` - | | - | while parsing this or-pattern starting here - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:37:16 - | -LL | A || B | => {} - | - ^ help: remove the `|` - | | - | while parsing this or-pattern starting here - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:39:17 - | -LL | | A | B | => {} - | - ^ help: remove the `|` - | | - | while parsing this or-pattern starting here - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:43:11 - | -LL | let a | : u8 = 0; - | - ^ help: remove the `|` - | | - | while parsing this or-pattern starting here - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:44:11 - | -LL | let a | = 0; - | - ^ help: remove the `|` - | | - | while parsing this or-pattern starting here - -error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:45:11 - | -LL | let a | ; - | - ^ help: remove the `|` - | | - | while parsing this or-pattern starting here -error: aborting due to 26 previous errors +error: aborting due to 11 previous errors diff --git a/src/test/ui/panic-runtime/libtest-unwinds.rs b/src/test/ui/panic-runtime/libtest-unwinds.rs new file mode 100644 index 0000000000000..bc13072612a29 --- /dev/null +++ b/src/test/ui/panic-runtime/libtest-unwinds.rs @@ -0,0 +1,10 @@ +// error-pattern:is not compiled with this crate's panic strategy `abort` +// compile-flags:-C panic=abort +// ignore-wasm32-bare compiled with panic=abort by default + +#![feature(test)] + +extern crate test; + +fn main() { +} diff --git a/src/test/ui/panic-runtime/libtest-unwinds.stderr b/src/test/ui/panic-runtime/libtest-unwinds.stderr new file mode 100644 index 0000000000000..704b81ae1ce08 --- /dev/null +++ b/src/test/ui/panic-runtime/libtest-unwinds.stderr @@ -0,0 +1,4 @@ +error: the linked panic runtime `panic_unwind` is not compiled with this crate's panic strategy `abort` + +error: aborting due to previous error + diff --git a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs index 6dcb852a3669f..5d72771c2dcff 100644 --- a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs +++ b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs @@ -4,7 +4,7 @@ // aux-build:wants-panic-runtime-abort.rs // aux-build:panic-runtime-lang-items.rs // error-pattern: is not compiled with this crate's panic strategy `unwind` -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![no_std] #![no_main] diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.rs b/src/test/ui/panic-runtime/want-unwind-got-abort.rs index e7811d40b5b9a..4c25c09d6438f 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort.rs +++ b/src/test/ui/panic-runtime/want-unwind-got-abort.rs @@ -1,7 +1,7 @@ // error-pattern:is incompatible with this crate's strategy of `unwind` // aux-build:panic-runtime-abort.rs // aux-build:panic-runtime-lang-items.rs -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![no_std] #![no_main] diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs index 44671796c01a3..478af451e7f65 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs +++ b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs @@ -2,7 +2,7 @@ // aux-build:panic-runtime-abort.rs // aux-build:wants-panic-runtime-abort.rs // aux-build:panic-runtime-lang-items.rs -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![no_std] #![no_main] diff --git a/src/test/ui/never_type/panic-uninitialized-zeroed.rs b/src/test/ui/panic-uninitialized-zeroed.rs similarity index 97% rename from src/test/ui/never_type/panic-uninitialized-zeroed.rs rename to src/test/ui/panic-uninitialized-zeroed.rs index 72b844d8b4886..b0d6629561803 100644 --- a/src/test/ui/never_type/panic-uninitialized-zeroed.rs +++ b/src/test/ui/panic-uninitialized-zeroed.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare always compiled as panic=abort right now and this requires unwinding // This test checks that instantiating an uninhabited type via `mem::{uninitialized,zeroed}` results // in a runtime panic. diff --git a/src/test/ui/parser/doc-inside-trait-item.stderr b/src/test/ui/parser/doc-inside-trait-item.stderr index 261e27b6e0d18..3287ece9ae644 100644 --- a/src/test/ui/parser/doc-inside-trait-item.stderr +++ b/src/test/ui/parser/doc-inside-trait-item.stderr @@ -8,4 +8,3 @@ LL | /// empty doc error: aborting due to previous error -For more information about this error, try `rustc --explain E0584`. diff --git a/src/test/ui/parser/intersection-patterns.rs b/src/test/ui/parser/intersection-patterns.rs deleted file mode 100644 index adb607cf6b97b..0000000000000 --- a/src/test/ui/parser/intersection-patterns.rs +++ /dev/null @@ -1,40 +0,0 @@ -// This tests the parser recovery in `recover_intersection_pat` -// and serves as a regression test for the diagnostics issue #65400. -// -// The general idea is that for `$pat_lhs @ $pat_rhs` where -// `$pat_lhs` is not generated by `ref? mut? $ident` we want -// to suggest either switching the order or note that intersection -// patterns are not allowed. - -fn main() { - let s: Option = None; - - match s { - Some(x) @ y => {} - //~^ ERROR pattern on wrong side of `@` - //~| pattern on the left, should be on the right - //~| binding on the right, should be on the left - //~| HELP switch the order - //~| SUGGESTION y @ Some(x) - _ => {} - } - - match s { - Some(x) @ Some(y) => {} - //~^ ERROR left-hand side of `@` must be a binding - //~| interpreted as a pattern, not a binding - //~| also a pattern - //~| NOTE bindings are `x`, `mut x`, `ref x`, and `ref mut x` - _ => {} - } - - match 2 { - 1 ..= 5 @ e => {} - //~^ ERROR pattern on wrong side of `@` - //~| pattern on the left, should be on the right - //~| binding on the right, should be on the left - //~| HELP switch the order - //~| SUGGESTION e @ 1 ..=5 - _ => {} - } -} diff --git a/src/test/ui/parser/intersection-patterns.stderr b/src/test/ui/parser/intersection-patterns.stderr deleted file mode 100644 index f5bfee5bbd611..0000000000000 --- a/src/test/ui/parser/intersection-patterns.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error: pattern on wrong side of `@` - --> $DIR/intersection-patterns.rs:13:9 - | -LL | Some(x) @ y => {} - | -------^^^- - | | | - | | binding on the right, should be on the left - | pattern on the left, should be on the right - | help: switch the order: `y @ Some(x)` - -error: left-hand side of `@` must be a binding - --> $DIR/intersection-patterns.rs:23:9 - | -LL | Some(x) @ Some(y) => {} - | -------^^^------- - | | | - | | also a pattern - | interpreted as a pattern, not a binding - | - = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` - -error: pattern on wrong side of `@` - --> $DIR/intersection-patterns.rs:32:9 - | -LL | 1 ..= 5 @ e => {} - | -------^^^- - | | | - | | binding on the right, should be on the left - | pattern on the left, should be on the right - | help: switch the order: `e @ 1 ..=5` - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/parser/issue-33413.rs b/src/test/ui/parser/issue-33413.rs index 7291732cebe4a..22f80a8aae866 100644 --- a/src/test/ui/parser/issue-33413.rs +++ b/src/test/ui/parser/issue-33413.rs @@ -3,7 +3,6 @@ struct S; impl S { fn f(*, a: u8) -> u8 {} //~^ ERROR expected parameter name, found `*` - //~| ERROR mismatched types } fn main() {} diff --git a/src/test/ui/parser/issue-33413.stderr b/src/test/ui/parser/issue-33413.stderr index 7e5c348e36cea..9e1178e8ac1f3 100644 --- a/src/test/ui/parser/issue-33413.stderr +++ b/src/test/ui/parser/issue-33413.stderr @@ -4,17 +4,5 @@ error: expected parameter name, found `*` LL | fn f(*, a: u8) -> u8 {} | ^ expected parameter name -error[E0308]: mismatched types - --> $DIR/issue-33413.rs:4:23 - | -LL | fn f(*, a: u8) -> u8 {} - | - ^^ expected u8, found () - | | - | implicitly returns `()` as its body has no tail or `return` expression - | - = note: expected type `u8` - found type `()` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. 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 deleted file mode 100644 index 97a405b6999c3..0000000000000 --- a/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs +++ /dev/null @@ -1,26 +0,0 @@ -// 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 deleted file mode 100644 index dd193d6a86ebd..0000000000000 --- a/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr +++ /dev/null @@ -1,45 +0,0 @@ -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/mismatched-delim-brace-empty-block.rs b/src/test/ui/parser/mismatched-delim-brace-empty-block.rs deleted file mode 100644 index 0f5a2cb09ecc4..0000000000000 --- a/src/test/ui/parser/mismatched-delim-brace-empty-block.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - -} - let _ = (); -} //~ ERROR unexpected close delimiter diff --git a/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr b/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr deleted file mode 100644 index 5ae5fc91a4e8a..0000000000000 --- a/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: unexpected close delimiter: `}` - --> $DIR/mismatched-delim-brace-empty-block.rs:5:1 - | -LL | fn main() { - | ___________- -LL | | -LL | | } - | |_- this block is empty, you might have not meant to close it -LL | let _ = (); -LL | } - | ^ unexpected close delimiter - -error: aborting due to previous error - diff --git a/src/test/ui/parser/no-const-fn-in-extern-block.rs b/src/test/ui/parser/no-const-fn-in-extern-block.rs deleted file mode 100644 index 29f26389ded18..0000000000000 --- a/src/test/ui/parser/no-const-fn-in-extern-block.rs +++ /dev/null @@ -1,8 +0,0 @@ -extern { - const fn foo(); - //~^ ERROR extern items cannot be `const` - const unsafe fn bar(); - //~^ ERROR extern items cannot be `const` -} - -fn main() {} diff --git a/src/test/ui/parser/no-const-fn-in-extern-block.stderr b/src/test/ui/parser/no-const-fn-in-extern-block.stderr deleted file mode 100644 index 5b4663a702f06..0000000000000 --- a/src/test/ui/parser/no-const-fn-in-extern-block.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: extern items cannot be `const` - --> $DIR/no-const-fn-in-extern-block.rs:2:5 - | -LL | const fn foo(); - | ^^^^^ - -error: extern items cannot be `const` - --> $DIR/no-const-fn-in-extern-block.rs:4:5 - | -LL | const unsafe fn bar(); - | ^^^^^ - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/parser/pat-lt-bracket-2.stderr b/src/test/ui/parser/pat-lt-bracket-2.stderr index 2191e31ad1ff2..dbc8d0f5865c6 100644 --- a/src/test/ui/parser/pat-lt-bracket-2.stderr +++ b/src/test/ui/parser/pat-lt-bracket-2.stderr @@ -3,12 +3,6 @@ error: expected one of `:`, `@`, or `|`, found `<` | LL | fn a(B<) {} | ^ expected one of `:`, `@`, or `|` here - | - = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this is a type, explicitly ignore the parameter name - | -LL | fn a(_: B<) {} - | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/pat-tuple-4.rs b/src/test/ui/parser/pat-tuple-4.rs index 6b8c146949aec..2f03160430a22 100644 --- a/src/test/ui/parser/pat-tuple-4.rs +++ b/src/test/ui/parser/pat-tuple-4.rs @@ -4,6 +4,7 @@ fn main() { match 0 { (.. PAT) => {} //~^ ERROR `..X` range patterns are not supported + //~| ERROR exclusive range pattern syntax is experimental } } diff --git a/src/test/ui/parser/pat-tuple-4.stderr b/src/test/ui/parser/pat-tuple-4.stderr index 1962dc4ff20a8..af3ecce184649 100644 --- a/src/test/ui/parser/pat-tuple-4.stderr +++ b/src/test/ui/parser/pat-tuple-4.stderr @@ -4,8 +4,17 @@ error: `..X` range patterns are not supported LL | (.. PAT) => {} | ^^^^^^ help: try using the minimum value for the type: `MIN..PAT` +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/pat-tuple-4.rs:5:10 + | +LL | (.. PAT) => {} + | ^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/37854 + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + error[E0308]: mismatched types - --> $DIR/pat-tuple-4.rs:10:30 + --> $DIR/pat-tuple-4.rs:11:30 | LL | const RECOVERY_WITNESS: () = 0; | ^ expected (), found integer @@ -13,6 +22,7 @@ LL | const RECOVERY_WITNESS: () = 0; = note: expected type `()` found type `{integer}` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/pat-tuple-5.stderr b/src/test/ui/parser/pat-tuple-5.stderr index 17155b4dd4954..09ebdc29a2161 100644 --- a/src/test/ui/parser/pat-tuple-5.stderr +++ b/src/test/ui/parser/pat-tuple-5.stderr @@ -5,10 +5,10 @@ LL | (PAT ..) => {} | ^^^^^^ help: try using the maximum value for the type: `PAT..MAX` error[E0658]: exclusive range pattern syntax is experimental - --> $DIR/pat-tuple-5.rs:5:14 + --> $DIR/pat-tuple-5.rs:5:10 | LL | (PAT ..) => {} - | ^^ + | ^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/37854 = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr index 32bb88d31c4c7..b46d3ca9c233c 100644 --- a/src/test/ui/parser/recover-from-bad-variant.stderr +++ b/src/test/ui/parser/recover-from-bad-variant.stderr @@ -12,9 +12,6 @@ LL | let x = Enum::Foo(a: 3, b: 4); error[E0532]: expected tuple struct/variant, found struct variant `Enum::Foo` --> $DIR/recover-from-bad-variant.rs:10:9 | -LL | Foo { a: usize, b: usize }, - | -------------------------- `Enum::Foo` defined here -... LL | Enum::Foo(a, b) => {} | ^^^^^^^^^ did you mean `Enum::Foo { /* fields */ }`? 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 9c7a25d589a1f..3dcc0c8f3d496 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -3,24 +3,15 @@ struct X; fn main() { false == false == false; - //~^ ERROR chained comparison operators require parentheses + //~^ ERROR: chained comparison operators require parentheses false == 0 < 2; - //~^ ERROR chained comparison operators require parentheses - //~| ERROR mismatched types - //~| ERROR mismatched types + //~^ ERROR: chained comparison operators require parentheses + //~| ERROR: mismatched types + //~| ERROR: mismatched types f(); //~^ ERROR chained comparison operators require parentheses - //~| HELP use `::<...>` instead of `<...>` to specify type arguments - - f, Option>>(1, 2); - //~^ ERROR chained comparison operators require parentheses - //~| HELP use `::<...>` instead of `<...>` to specify type arguments - - use std::convert::identity; - let _ = identity; - //~^ ERROR chained comparison operators require parentheses - //~| HELP use `::<...>` instead of `<...>` to specify type arguments - //~| HELP or use `(...)` if you meant to specify fn arguments + //~| 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 5aa37a40cbd3d..e927f4c32484e 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -2,41 +2,21 @@ error: chained comparison operators require parentheses --> $DIR/require-parens-for-chained-comparison.rs:5:11 | LL | false == false == false; - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: chained comparison operators require parentheses --> $DIR/require-parens-for-chained-comparison.rs:8:11 | LL | false == 0 < 2; - | ^^^^^^ + | ^^^^^^^^ error: chained comparison operators require parentheses --> $DIR/require-parens-for-chained-comparison.rs:13:6 | LL | f(); - | ^^^ -help: use `::<...>` instead of `<...>` to specify type arguments + | ^^^^ | -LL | f::(); - | ^^ - -error: chained comparison operators require parentheses - --> $DIR/require-parens-for-chained-comparison.rs:17:6 - | -LL | f, Option>>(1, 2); - | ^^^^^^^^ -help: use `::<...>` instead of `<...>` to specify type arguments - | -LL | f::, Option>>(1, 2); - | ^^ - -error: chained comparison operators require parentheses - --> $DIR/require-parens-for-chained-comparison.rs:22:21 - | -LL | let _ = identity; - | ^^^^ - | - = help: use `::<...>` instead of `<...>` to specify type arguments + = help: use `::<...>` instead of `<...>` if you meant to specify type arguments = help: or use `(...)` if you meant to specify fn arguments error[E0308]: mismatched types @@ -57,6 +37,6 @@ LL | false == 0 < 2; = note: expected type `bool` found type `{integer}` -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/partialeq_help.stderr b/src/test/ui/partialeq_help.stderr index 6acc09b62c811..9021bd30a7781 100644 --- a/src/test/ui/partialeq_help.stderr +++ b/src/test/ui/partialeq_help.stderr @@ -5,6 +5,7 @@ LL | a == b; | ^^ no implementation for `&T == T` | = help: the trait `std::cmp::PartialEq` is not implemented for `&T` + = help: consider adding a `where &T: std::cmp::PartialEq` bound error: aborting due to previous error diff --git a/src/test/ui/pattern/rest-pat-syntactic.rs b/src/test/ui/pattern/rest-pat-syntactic.rs index 45b31f6125374..9656a0b5de9ce 100644 --- a/src/test/ui/pattern/rest-pat-syntactic.rs +++ b/src/test/ui/pattern/rest-pat-syntactic.rs @@ -3,8 +3,6 @@ // check-pass -#![feature(box_patterns)] - fn main() {} macro_rules! accept_pat { diff --git a/src/test/ui/phantom-oibit.stderr b/src/test/ui/phantom-oibit.stderr index 4d9d06b8986d5..ac48ee0cb0fe3 100644 --- a/src/test/ui/phantom-oibit.stderr +++ b/src/test/ui/phantom-oibit.stderr @@ -3,13 +3,12 @@ error[E0277]: `T` cannot be shared between threads safely | LL | fn is_zen(_: T) {} | ------ --- required by this bound in `is_zen` -LL | -LL | fn not_sync(x: Guard) { - | - help: consider restricting this bound: `T: std::marker::Sync` +... LL | is_zen(x) | ^ `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>` @@ -20,12 +19,11 @@ error[E0277]: `T` cannot be shared between threads safely LL | fn is_zen(_: T) {} | ------ --- required by this bound in `is_zen` ... -LL | fn nested_not_sync(x: Nested>) { - | - help: consider restricting this bound: `T: std::marker::Sync` LL | is_zen(x) | ^ `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>` diff --git a/src/test/ui/precise_pointer_size_matching.rs b/src/test/ui/precise_pointer_size_matching.rs index 54aeb8616d959..759b63b188b35 100644 --- a/src/test/ui/precise_pointer_size_matching.rs +++ b/src/test/ui/precise_pointer_size_matching.rs @@ -8,7 +8,7 @@ #![feature(precise_pointer_size_matching)] #![feature(exclusive_range_pattern)] -#![deny(unreachable_patterns, overlapping_patterns)] +#![deny(unreachable_patterns)] use std::{usize, isize}; diff --git a/src/test/ui/privacy/privacy-ns1.stderr b/src/test/ui/privacy/privacy-ns1.stderr index 8ffc12c31cb66..09148f9d0e6e1 100644 --- a/src/test/ui/privacy/privacy-ns1.stderr +++ b/src/test/ui/privacy/privacy-ns1.stderr @@ -72,5 +72,5 @@ LL | use foo3::Bar; error: aborting due to 4 previous errors -Some errors have detailed explanations: E0412, E0423, E0425, E0573. +Some errors have detailed explanations: E0412, E0423, E0425. For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr index 13057a899f3c9..8ea32f36f9e7a 100644 --- a/src/test/ui/privacy/privacy-ns2.stderr +++ b/src/test/ui/privacy/privacy-ns2.stderr @@ -82,5 +82,5 @@ LL | use foo3::{Bar,Baz}; error: aborting due to 7 previous errors -Some errors have detailed explanations: E0423, E0573, E0603. +Some errors have detailed explanations: E0423, E0603. For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/privacy/privacy5.rs b/src/test/ui/privacy/privacy5.rs index 3dc26b1955cd7..741ba0be2c2b6 100644 --- a/src/test/ui/privacy/privacy5.rs +++ b/src/test/ui/privacy/privacy5.rs @@ -48,31 +48,31 @@ mod a { } fn this_crate() { - let a = a::A(()); //~ ERROR tuple struct constructor `A` is private - let b = a::B(2); //~ ERROR tuple struct constructor `B` is private - let c = a::C(2, 3); //~ ERROR tuple struct constructor `C` is private + let a = a::A(()); //~ ERROR tuple struct `A` is private + let b = a::B(2); //~ ERROR tuple struct `B` is private + let c = a::C(2, 3); //~ ERROR tuple struct `C` is private let d = a::D(4); - let a::A(()) = a; //~ ERROR tuple struct constructor `A` is private - let a::A(_) = a; //~ ERROR tuple struct constructor `A` is private - match a { a::A(()) => {} } //~ ERROR tuple struct constructor `A` is private - match a { a::A(_) => {} } //~ ERROR tuple struct constructor `A` is private - - let a::B(_) = b; //~ ERROR tuple struct constructor `B` is private - let a::B(_b) = b; //~ ERROR tuple struct constructor `B` is private - match b { a::B(_) => {} } //~ ERROR tuple struct constructor `B` is private - match b { a::B(_b) => {} } //~ ERROR tuple struct constructor `B` is private - match b { a::B(1) => {} a::B(_) => {} } //~ ERROR tuple struct constructor `B` is private - //~^ ERROR tuple struct constructor `B` is private - - let a::C(_, _) = c; //~ ERROR tuple struct constructor `C` is private - let a::C(_a, _) = c; //~ ERROR tuple struct constructor `C` is private - let a::C(_, _b) = c; //~ ERROR tuple struct constructor `C` is private - let a::C(_a, _b) = c; //~ ERROR tuple struct constructor `C` is private - match c { a::C(_, _) => {} } //~ ERROR tuple struct constructor `C` is private - match c { a::C(_a, _) => {} } //~ ERROR tuple struct constructor `C` is private - match c { a::C(_, _b) => {} } //~ ERROR tuple struct constructor `C` is private - match c { a::C(_a, _b) => {} } //~ ERROR tuple struct constructor `C` is private + let a::A(()) = a; //~ ERROR tuple struct `A` is private + let a::A(_) = a; //~ ERROR tuple struct `A` is private + match a { a::A(()) => {} } //~ ERROR tuple struct `A` is private + match a { a::A(_) => {} } //~ ERROR tuple struct `A` is private + + let a::B(_) = b; //~ ERROR tuple struct `B` is private + let a::B(_b) = b; //~ ERROR tuple struct `B` is private + match b { a::B(_) => {} } //~ ERROR tuple struct `B` is private + match b { a::B(_b) => {} } //~ ERROR tuple struct `B` is private + match b { a::B(1) => {} a::B(_) => {} } //~ ERROR tuple struct `B` is private + //~^ ERROR tuple struct `B` is private + + let a::C(_, _) = c; //~ ERROR tuple struct `C` is private + let a::C(_a, _) = c; //~ ERROR tuple struct `C` is private + let a::C(_, _b) = c; //~ ERROR tuple struct `C` is private + let a::C(_a, _b) = c; //~ ERROR tuple struct `C` is private + match c { a::C(_, _) => {} } //~ ERROR tuple struct `C` is private + match c { a::C(_a, _) => {} } //~ ERROR tuple struct `C` is private + match c { a::C(_, _b) => {} } //~ ERROR tuple struct `C` is private + match c { a::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private let a::D(_) = d; let a::D(_d) = d; @@ -80,38 +80,38 @@ fn this_crate() { match d { a::D(_d) => {} } match d { a::D(1) => {} a::D(_) => {} } - let a2 = a::A; //~ ERROR tuple struct constructor `A` is private - let b2 = a::B; //~ ERROR tuple struct constructor `B` is private - let c2 = a::C; //~ ERROR tuple struct constructor `C` is private + let a2 = a::A; //~ ERROR tuple struct `A` is private + let b2 = a::B; //~ ERROR tuple struct `B` is private + let c2 = a::C; //~ ERROR tuple struct `C` is private let d2 = a::D; } fn xcrate() { - let a = other::A(()); //~ ERROR tuple struct constructor `A` is private - let b = other::B(2); //~ ERROR tuple struct constructor `B` is private - let c = other::C(2, 3); //~ ERROR tuple struct constructor `C` is private + let a = other::A(()); //~ ERROR tuple struct `A` is private + let b = other::B(2); //~ ERROR tuple struct `B` is private + let c = other::C(2, 3); //~ ERROR tuple struct `C` is private let d = other::D(4); - let other::A(()) = a; //~ ERROR tuple struct constructor `A` is private - let other::A(_) = a; //~ ERROR tuple struct constructor `A` is private - match a { other::A(()) => {} } //~ ERROR tuple struct constructor `A` is private - match a { other::A(_) => {} } //~ ERROR tuple struct constructor `A` is private - - let other::B(_) = b; //~ ERROR tuple struct constructor `B` is private - let other::B(_b) = b; //~ ERROR tuple struct constructor `B` is private - match b { other::B(_) => {} } //~ ERROR tuple struct constructor `B` is private - match b { other::B(_b) => {} } //~ ERROR tuple struct constructor `B` is private - match b { other::B(1) => {}//~ ERROR tuple struct constructor `B` is private - other::B(_) => {} } //~ ERROR tuple struct constructor `B` is private - - let other::C(_, _) = c; //~ ERROR tuple struct constructor `C` is private - let other::C(_a, _) = c; //~ ERROR tuple struct constructor `C` is private - let other::C(_, _b) = c; //~ ERROR tuple struct constructor `C` is private - let other::C(_a, _b) = c; //~ ERROR tuple struct constructor `C` is private - match c { other::C(_, _) => {} } //~ ERROR tuple struct constructor `C` is private - match c { other::C(_a, _) => {} } //~ ERROR tuple struct constructor `C` is private - match c { other::C(_, _b) => {} } //~ ERROR tuple struct constructor `C` is private - match c { other::C(_a, _b) => {} } //~ ERROR tuple struct constructor `C` is private + let other::A(()) = a; //~ ERROR tuple struct `A` is private + let other::A(_) = a; //~ ERROR tuple struct `A` is private + match a { other::A(()) => {} } //~ ERROR tuple struct `A` is private + match a { other::A(_) => {} } //~ ERROR tuple struct `A` is private + + let other::B(_) = b; //~ ERROR tuple struct `B` is private + let other::B(_b) = b; //~ ERROR tuple struct `B` is private + match b { other::B(_) => {} } //~ ERROR tuple struct `B` is private + match b { other::B(_b) => {} } //~ ERROR tuple struct `B` is private + match b { other::B(1) => {} other::B(_) => {} } //~ ERROR tuple struct `B` is private + //~^ ERROR tuple struct `B` is private + + let other::C(_, _) = c; //~ ERROR tuple struct `C` is private + let other::C(_a, _) = c; //~ ERROR tuple struct `C` is private + let other::C(_, _b) = c; //~ ERROR tuple struct `C` is private + let other::C(_a, _b) = c; //~ ERROR tuple struct `C` is private + match c { other::C(_, _) => {} } //~ ERROR tuple struct `C` is private + match c { other::C(_a, _) => {} } //~ ERROR tuple struct `C` is private + match c { other::C(_, _b) => {} } //~ ERROR tuple struct `C` is private + match c { other::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private let other::D(_) = d; let other::D(_d) = d; @@ -119,9 +119,9 @@ fn xcrate() { match d { other::D(_d) => {} } match d { other::D(1) => {} other::D(_) => {} } - let a2 = other::A; //~ ERROR tuple struct constructor `A` is private - let b2 = other::B; //~ ERROR tuple struct constructor `B` is private - let c2 = other::C; //~ ERROR tuple struct constructor `C` is private + let a2 = other::A; //~ ERROR tuple struct `A` is private + let b2 = other::B; //~ ERROR tuple struct `B` is private + let c2 = other::C; //~ ERROR tuple struct `C` is private let d2 = other::D; } diff --git a/src/test/ui/privacy/privacy5.stderr b/src/test/ui/privacy/privacy5.stderr index 2ee83149b695f..532d1ac1e2fb8 100644 --- a/src/test/ui/privacy/privacy5.stderr +++ b/src/test/ui/privacy/privacy5.stderr @@ -1,482 +1,386 @@ -error[E0603]: tuple struct constructor `A` is private +error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:51:16 | -LL | pub struct A(()); - | -- a constructor is private if any of the fields is private -... LL | let a = a::A(()); | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:52:16 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private -... LL | let b = a::B(2); | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:53:16 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private -... LL | let c = a::C(2, 3); | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `A` is private +error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:56:12 | -LL | pub struct A(()); - | -- a constructor is private if any of the fields is private -... LL | let a::A(()) = a; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `A` is private +error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:57:12 | -LL | pub struct A(()); - | -- a constructor is private if any of the fields is private -... LL | let a::A(_) = a; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `A` is private +error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:58:18 | -LL | pub struct A(()); - | -- a constructor is private if any of the fields is private -... LL | match a { a::A(()) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `A` is private +error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:59:18 | -LL | pub struct A(()); - | -- a constructor is private if any of the fields is private -... LL | match a { a::A(_) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:61:12 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private -... LL | let a::B(_) = b; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:62:12 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private -... LL | let a::B(_b) = b; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:63:18 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private -... LL | match b { a::B(_) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:64:18 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private -... LL | match b { a::B(_b) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:65:18 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private -... LL | match b { a::B(1) => {} a::B(_) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:65:32 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private -... LL | match b { a::B(1) => {} a::B(_) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:68:12 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private -... LL | let a::C(_, _) = c; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:69:12 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private -... LL | let a::C(_a, _) = c; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:70:12 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private -... LL | let a::C(_, _b) = c; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:71:12 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private -... LL | let a::C(_a, _b) = c; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:72:18 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private -... LL | match c { a::C(_, _) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:73:18 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private -... LL | match c { a::C(_a, _) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:74:18 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private -... LL | match c { a::C(_, _b) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:75:18 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private -... LL | match c { a::C(_a, _b) => {} } | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `A` is private +error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:83:17 | -LL | pub struct A(()); - | -- a constructor is private if any of the fields is private -... LL | let a2 = a::A; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:84:17 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private -... LL | let b2 = a::B; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:85:17 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private -... LL | let c2 = a::C; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `A` is private +error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:90:20 | LL | let a = other::A(()); | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | -LL | pub struct A(()); - | -- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:91:20 | LL | let b = other::B(2); | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:92:20 | LL | let c = other::C(2, 3); | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `A` is private +error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:95:16 | LL | let other::A(()) = a; | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | -LL | pub struct A(()); - | -- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `A` is private +error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:96:16 | LL | let other::A(_) = a; | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | -LL | pub struct A(()); - | -- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `A` is private +error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:97:22 | LL | match a { other::A(()) => {} } | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | -LL | pub struct A(()); - | -- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `A` is private +error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:98:22 | LL | match a { other::A(_) => {} } | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | -LL | pub struct A(()); - | -- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:100:16 | LL | let other::B(_) = b; | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:101:16 | LL | let other::B(_b) = b; | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:102:22 | LL | match b { other::B(_) => {} } | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:103:22 | LL | match b { other::B(_b) => {} } | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:104:22 | -LL | match b { other::B(1) => {} +LL | match b { other::B(1) => {} other::B(_) => {} } | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private - --> $DIR/privacy5.rs:105:16 +error[E0603]: tuple struct `B` is private + --> $DIR/privacy5.rs:104:40 | -LL | other::B(_) => {} } - | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 +LL | match b { other::B(1) => {} other::B(_) => {} } + | ^ | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:107:16 | LL | let other::C(_, _) = c; | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:108:16 | LL | let other::C(_a, _) = c; | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:109:16 | LL | let other::C(_, _b) = c; | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:110:16 | LL | let other::C(_a, _b) = c; | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:111:22 | LL | match c { other::C(_, _) => {} } | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:112:22 | LL | match c { other::C(_a, _) => {} } | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:113:22 | LL | match c { other::C(_, _b) => {} } | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:114:22 | LL | match c { other::C(_a, _b) => {} } | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `A` is private +error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:122:21 | LL | let a2 = other::A; | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | -LL | pub struct A(()); - | -- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `B` is private +error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:123:21 | LL | let b2 = other::B; | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | -LL | pub struct B(isize); - | ----- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `C` is private +error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:124:21 | LL | let c2 = other::C; | ^ - | - ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | -LL | pub struct C(pub isize, isize); - | ---------------- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private error: aborting due to 48 previous errors diff --git a/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs b/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs deleted file mode 100644 index 548fefe76f571..0000000000000 --- a/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs +++ /dev/null @@ -1,23 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; -use proc_macro::*; - -#[proc_macro] -pub fn gen_macro_rules(_: TokenStream) -> TokenStream { - " - macro_rules! generated {() => { - struct ItemDef; - let local_def = 0; - - ItemUse; // OK - local_use; // ERROR - break 'label_use; // ERROR - - type DollarCrate = $crate::ItemUse; // OK - }} - ".parse().unwrap() -} diff --git a/src/test/ui/proc-macro/auxiliary/mixed-site-span.rs b/src/test/ui/proc-macro/auxiliary/mixed-site-span.rs deleted file mode 100644 index dea5ea04aa850..0000000000000 --- a/src/test/ui/proc-macro/auxiliary/mixed-site-span.rs +++ /dev/null @@ -1,42 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![feature(proc_macro_hygiene)] -#![feature(proc_macro_mixed_site)] -#![feature(proc_macro_quote)] - -#![crate_type = "proc-macro"] - -extern crate proc_macro; -use proc_macro::*; - -#[proc_macro] -pub fn proc_macro_rules(input: TokenStream) -> TokenStream { - if input.is_empty() { - let id = |s| TokenTree::from(Ident::new(s, Span::mixed_site())); - let item_def = id("ItemDef"); - let local_def = id("local_def"); - let item_use = id("ItemUse"); - let local_use = id("local_use"); - let mut single_quote = Punct::new('\'', Spacing::Joint); - single_quote.set_span(Span::mixed_site()); - let label_use: TokenStream = [ - TokenTree::from(single_quote), - id("label_use"), - ].iter().cloned().collect(); - quote!( - struct $item_def; - let $local_def = 0; - - $item_use; // OK - $local_use; // ERROR - break $label_use; // ERROR - ) - } else { - let mut dollar_crate = input.into_iter().next().unwrap(); - dollar_crate.set_span(Span::mixed_site()); - quote!( - type A = $dollar_crate::ItemUse; - ) - } -} diff --git a/src/test/ui/proc-macro/auxiliary/more-gates.rs b/src/test/ui/proc-macro/auxiliary/more-gates.rs new file mode 100644 index 0000000000000..6b609eaee1295 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/more-gates.rs @@ -0,0 +1,35 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_attribute] +pub fn attr2mac1(_: TokenStream, _: TokenStream) -> TokenStream { + "macro_rules! foo1 { (a) => (a) }".parse().unwrap() +} + +#[proc_macro_attribute] +pub fn attr2mac2(_: TokenStream, _: TokenStream) -> TokenStream { + "macro foo2(a) { a }".parse().unwrap() +} + +#[proc_macro] +pub fn mac2mac1(_: TokenStream) -> TokenStream { + "macro_rules! foo3 { (a) => (a) }".parse().unwrap() +} + +#[proc_macro] +pub fn mac2mac2(_: TokenStream) -> TokenStream { + "macro foo4(a) { a }".parse().unwrap() +} + +#[proc_macro] +pub fn tricky(_: TokenStream) -> TokenStream { + "fn foo() { + macro_rules! foo { (a) => (a) } + }".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/test-macros-rpass.rs b/src/test/ui/proc-macro/auxiliary/test-macros-rpass.rs new file mode 100644 index 0000000000000..15fe3804f9b4f --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/test-macros-rpass.rs @@ -0,0 +1,26 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn nop_attr(_attr: TokenStream, input: TokenStream) -> TokenStream { + assert!(_attr.to_string().is_empty()); + input +} + +#[proc_macro_attribute] +pub fn no_output(_attr: TokenStream, _input: TokenStream) -> TokenStream { + assert!(_attr.to_string().is_empty()); + assert!(!_input.to_string().is_empty()); + "".parse().unwrap() +} + +#[proc_macro] +pub fn emit_input(input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui/proc-macro/disappearing-resolution.rs b/src/test/ui/proc-macro/disappearing-resolution.rs deleted file mode 100644 index a01b8f302cae3..0000000000000 --- a/src/test/ui/proc-macro/disappearing-resolution.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Regression test for issue #64803 (initial attribute resolution can disappear later). - -// aux-build:test-macros.rs - -#[macro_use] -extern crate test_macros; - -mod m { - use test_macros::Empty; -} -use m::Empty; //~ ERROR derive macro `Empty` is private - -// To resolve `empty_helper` we need to resolve `Empty`. -// During initial resolution `use m::Empty` introduces no entries, so we proceed to `macro_use`, -// successfully resolve `Empty` from there, and then resolve `empty_helper` as its helper. -// During validation `use m::Empty` introduces a `Res::Err` stub, so `Empty` resolves to it, -// and `empty_helper` can no longer be resolved. -#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope -#[derive(Empty)] -struct S; - -fn main() {} diff --git a/src/test/ui/proc-macro/disappearing-resolution.stderr b/src/test/ui/proc-macro/disappearing-resolution.stderr deleted file mode 100644 index a3377ef515f91..0000000000000 --- a/src/test/ui/proc-macro/disappearing-resolution.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: cannot find attribute `empty_helper` in this scope - --> $DIR/disappearing-resolution.rs:18:3 - | -LL | #[empty_helper] - | ^^^^^^^^^^^^ - -error[E0603]: derive macro `Empty` is private - --> $DIR/disappearing-resolution.rs:11:8 - | -LL | use m::Empty; - | ^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0603`. diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.rs b/src/test/ui/proc-macro/dollar-crate-issue-62325.rs index 223c4047cb2b1..b7b152e669213 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-62325.rs +++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.rs @@ -7,6 +7,8 @@ // normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)" // normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)" +#![feature(proc_macro_hygiene)] + #[macro_use] extern crate test_macros; extern crate dollar_crate_external; 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 619b2fd5321ff..7ee8078b2c5d2 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout @@ -59,54 +59,54 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): struct B (identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #10 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Ident { ident: "B", - span: #10 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "identity", - span: #10 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Punct { ch: '!', spacing: Alone, - span: #10 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #10 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #10 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #10 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Ident { ident: "S", - span: #10 bytes(LO..HI), + span: #8 bytes(LO..HI), }, ], - span: #10 bytes(LO..HI), + span: #8 bytes(LO..HI), }, ], - span: #10 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #10 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 5fdc6f8ee96ca..4f7e000265eb0 100644 --- a/src/test/ui/proc-macro/dollar-crate.stdout +++ b/src/test/ui/proc-macro/dollar-crate.stdout @@ -124,40 +124,40 @@ PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "M", - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "S", - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ], - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #13 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: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "A", - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "S", - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ], - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #13 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: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "D", - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "S", - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ], - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #13 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ] diff --git a/src/test/ui/proc-macro/expand-with-a-macro.rs b/src/test/ui/proc-macro/expand-with-a-macro.rs index 690a76ef3e0af..418178d0f0ead 100644 --- a/src/test/ui/proc-macro/expand-with-a-macro.rs +++ b/src/test/ui/proc-macro/expand-with-a-macro.rs @@ -1,7 +1,7 @@ // run-pass // aux-build:expand-with-a-macro.rs -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![deny(warnings)] diff --git a/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs b/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs deleted file mode 100644 index 195bda82e9ce1..0000000000000 --- a/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs +++ /dev/null @@ -1,23 +0,0 @@ -// `macro_rules` items produced by transparent macros have correct hygiene in basic cases. -// Local variables and labels are hygienic, items are not hygienic. -// `$crate` refers to the crate that defines `macro_rules` and not the outer transparent macro. - -// aux-build:gen-macro-rules-hygiene.rs - -#[macro_use] -extern crate gen_macro_rules_hygiene; - -struct ItemUse; - -gen_macro_rules!(); -//~^ ERROR use of undeclared label `'label_use` -//~| ERROR cannot find value `local_use` in this scope - -fn main() { - 'label_use: loop { - let local_use = 1; - generated!(); - ItemDef; // OK - local_def; //~ ERROR cannot find value `local_def` in this scope - } -} diff --git a/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr deleted file mode 100644 index ecebdfa965666..0000000000000 --- a/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0426]: use of undeclared label `'label_use` - --> $DIR/gen-macro-rules-hygiene.rs:12:1 - | -LL | gen_macro_rules!(); - | ^^^^^^^^^^^^^^^^^^^ undeclared label `'label_use` -... -LL | generated!(); - | ------------- in this macro invocation - -error[E0425]: cannot find value `local_use` in this scope - --> $DIR/gen-macro-rules-hygiene.rs:12:1 - | -LL | gen_macro_rules!(); - | ^^^^^^^^^^^^^^^^^^^ not found in this scope -... -LL | generated!(); - | ------------- in this macro invocation - -error[E0425]: cannot find value `local_def` in this scope - --> $DIR/gen-macro-rules-hygiene.rs:21:9 - | -LL | local_def; - | ^^^^^^^^^ not found in this scope - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0425, E0426. -For more information about an error, try `rustc --explain E0425`. 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 9de57da5af434..94a4b403d5a3f 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-1.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs @@ -1,5 +1,4 @@ // aux-build:invalid-punct-ident.rs -// rustc-env:RUST_BACKTRACE=0 // FIXME https://github.com/rust-lang/rust/issues/59998 // normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> "" 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 fc821d29d5a0c..107f5fb515b1c 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:16: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 79f72324b1d89..778b7eeecd7a9 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-2.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs @@ -1,5 +1,4 @@ // aux-build:invalid-punct-ident.rs -// rustc-env:RUST_BACKTRACE=0 // FIXME https://github.com/rust-lang/rust/issues/59998 // normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> "" 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 8b30edaf85c09..f1b9ecc6cbfe4 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:16: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 d01e9b699cac5..f68ee3de7f456 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-3.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs @@ -1,5 +1,4 @@ // aux-build:invalid-punct-ident.rs -// rustc-env:RUST_BACKTRACE=0 // FIXME https://github.com/rust-lang/rust/issues/59998 // normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> "" 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 d46fab08e14f0..6044b9887401e 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:16:1 + --> $DIR/invalid-punct-ident-3.rs:15:1 | LL | invalid_raw_ident!(); | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/lifetimes.rs b/src/test/ui/proc-macro/lifetimes.rs index 5605696715e34..d0dd1b4603b16 100644 --- a/src/test/ui/proc-macro/lifetimes.rs +++ b/src/test/ui/proc-macro/lifetimes.rs @@ -1,5 +1,7 @@ // aux-build:lifetimes.rs +#![feature(proc_macro_hygiene)] + extern crate lifetimes; use lifetimes::*; diff --git a/src/test/ui/proc-macro/lifetimes.stderr b/src/test/ui/proc-macro/lifetimes.stderr index 10acd4304aa23..6e91201405cc6 100644 --- a/src/test/ui/proc-macro/lifetimes.stderr +++ b/src/test/ui/proc-macro/lifetimes.stderr @@ -1,5 +1,5 @@ error: expected type, found `'` - --> $DIR/lifetimes.rs:7:10 + --> $DIR/lifetimes.rs:9:10 | LL | type A = single_quote_alone!(); | ^^^^^^^^^^^^^^^^^^^^^ this macro call doesn't expand to a type diff --git a/src/test/ui/proc-macro/macros-in-extern-derive.rs b/src/test/ui/proc-macro/macros-in-extern-derive.rs deleted file mode 100644 index d2751a353bd93..0000000000000 --- a/src/test/ui/proc-macro/macros-in-extern-derive.rs +++ /dev/null @@ -1,6 +0,0 @@ -extern { - #[derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions - fn f(); -} - -fn main() {} diff --git a/src/test/ui/proc-macro/macros-in-extern-derive.stderr b/src/test/ui/proc-macro/macros-in-extern-derive.stderr deleted file mode 100644 index e2afb7d34c149..0000000000000 --- a/src/test/ui/proc-macro/macros-in-extern-derive.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `derive` may only be applied to structs, enums and unions - --> $DIR/macros-in-extern-derive.rs:2:5 - | -LL | #[derive(Copy)] - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/proc-macro/macros-in-extern-rpass.rs b/src/test/ui/proc-macro/macros-in-extern-rpass.rs new file mode 100644 index 0000000000000..a30a287a1011b --- /dev/null +++ b/src/test/ui/proc-macro/macros-in-extern-rpass.rs @@ -0,0 +1,25 @@ +// run-pass +// aux-build:test-macros-rpass.rs +// ignore-wasm32 + +#![feature(macros_in_extern)] + +extern crate test_macros_rpass as test_macros; + +use test_macros::{nop_attr, no_output, emit_input}; + +fn main() { + assert_eq!(unsafe { rust_get_test_int() }, 1isize); + assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEF); +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern { + #[no_output] + fn some_definitely_unknown_symbol_which_should_be_removed(); + + #[nop_attr] + fn rust_get_test_int() -> isize; + + emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;); +} diff --git a/src/test/ui/proc-macro/macros-in-type.rs b/src/test/ui/proc-macro/macros-in-type.rs deleted file mode 100644 index 19ed58eceb964..0000000000000 --- a/src/test/ui/proc-macro/macros-in-type.rs +++ /dev/null @@ -1,11 +0,0 @@ -// check-pass -// aux-build:test-macros.rs - -#[macro_use] -extern crate test_macros; - -const C: identity!(u8) = 10; - -fn main() { - let c: u8 = C; -} diff --git a/src/test/ui/proc-macro/mixed-site-span.rs b/src/test/ui/proc-macro/mixed-site-span.rs deleted file mode 100644 index 69c32a96ca055..0000000000000 --- a/src/test/ui/proc-macro/mixed-site-span.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Proc macros using `mixed_site` spans exhibit usual properties of `macro_rules` hygiene. - -// aux-build:mixed-site-span.rs - -#![feature(proc_macro_hygiene)] - -#[macro_use] -extern crate mixed_site_span; - -struct ItemUse; - -fn main() { - 'label_use: loop { - let local_use = 1; - proc_macro_rules!(); - //~^ ERROR use of undeclared label `'label_use` - //~| ERROR cannot find value `local_use` in this scope - ItemDef; // OK - local_def; //~ ERROR cannot find value `local_def` in this scope - } -} - -macro_rules! pass_dollar_crate { - () => (proc_macro_rules!($crate);) //~ ERROR cannot find type `ItemUse` in crate `$crate` -} -pass_dollar_crate!(); diff --git a/src/test/ui/proc-macro/mixed-site-span.stderr b/src/test/ui/proc-macro/mixed-site-span.stderr deleted file mode 100644 index 475e3e0ca359b..0000000000000 --- a/src/test/ui/proc-macro/mixed-site-span.stderr +++ /dev/null @@ -1,49 +0,0 @@ -error[E0426]: use of undeclared label `'label_use` - --> $DIR/mixed-site-span.rs:15:9 - | -LL | proc_macro_rules!(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | undeclared label `'label_use` - | in this macro invocation - -error[E0425]: cannot find value `local_use` in this scope - --> $DIR/mixed-site-span.rs:15:9 - | -LL | proc_macro_rules!(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | not found in this scope - | in this macro invocation - -error[E0425]: cannot find value `local_def` in this scope - --> $DIR/mixed-site-span.rs:19:9 - | -LL | local_def; - | ^^^^^^^^^ not found in this scope - -error[E0412]: cannot find type `ItemUse` in crate `$crate` - --> $DIR/auxiliary/mixed-site-span.rs:14:1 - | -LL | / pub fn proc_macro_rules(input: TokenStream) -> TokenStream { -LL | | if input.is_empty() { -LL | | let id = |s| TokenTree::from(Ident::new(s, Span::mixed_site())); -LL | | let item_def = id("ItemDef"); -... | -LL | | } -LL | | } - | |_^ not found in `$crate` - | - ::: $DIR/mixed-site-span.rs:26:1 - | -LL | pass_dollar_crate!(); - | --------------------- in this macro invocation -help: possible candidate is found in another module, you can import it into scope - | -LL | use ItemUse; - | - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0412, E0425, E0426. -For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/proc-macro/more-gates.rs b/src/test/ui/proc-macro/more-gates.rs new file mode 100644 index 0000000000000..b870b438a6540 --- /dev/null +++ b/src/test/ui/proc-macro/more-gates.rs @@ -0,0 +1,22 @@ +// aux-build:more-gates.rs + +#![feature(decl_macro)] + +extern crate more_gates as foo; + +use foo::*; + +#[attr2mac1] +//~^ ERROR: cannot expand to macro definitions +pub fn a() {} +#[attr2mac2] +//~^ ERROR: cannot expand to macro definitions +pub fn a() {} + +mac2mac1!(); //~ ERROR: cannot expand to macro definitions +mac2mac2!(); //~ ERROR: cannot expand to macro definitions + +tricky!(); +//~^ ERROR: cannot expand to macro definitions + +fn main() {} diff --git a/src/test/ui/proc-macro/more-gates.stderr b/src/test/ui/proc-macro/more-gates.stderr new file mode 100644 index 0000000000000..ad96f78c77ad0 --- /dev/null +++ b/src/test/ui/proc-macro/more-gates.stderr @@ -0,0 +1,48 @@ +error[E0658]: procedural macros cannot expand to macro definitions + --> $DIR/more-gates.rs:9:1 + | +LL | #[attr2mac1] + | ^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54727 + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: procedural macros cannot expand to macro definitions + --> $DIR/more-gates.rs:12:1 + | +LL | #[attr2mac2] + | ^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54727 + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: procedural macros cannot expand to macro definitions + --> $DIR/more-gates.rs:16:1 + | +LL | mac2mac1!(); + | ^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54727 + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: procedural macros cannot expand to macro definitions + --> $DIR/more-gates.rs:17:1 + | +LL | mac2mac2!(); + | ^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54727 + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: procedural macros cannot expand to macro definitions + --> $DIR/more-gates.rs:19:1 + | +LL | tricky!(); + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54727 + = help: add `#![feature(proc_macro_hygiene)]` 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/proc-macro/proc-macro-deprecated-attr.rs b/src/test/ui/proc-macro/proc-macro-deprecated-attr.rs deleted file mode 100644 index f1144a4a55b16..0000000000000 --- a/src/test/ui/proc-macro/proc-macro-deprecated-attr.rs +++ /dev/null @@ -1,16 +0,0 @@ -// check-pass -// force-host -// no-prefer-dynamic - -#![deny(deprecated)] - -#![crate_type = "proc-macro"] - -extern crate proc_macro; -use proc_macro::*; - -#[proc_macro] -#[deprecated(since = "1.0.0", note = "test")] -pub fn test_compile_without_warning_with_deprecated(_: TokenStream) -> TokenStream { - TokenStream::new() -} diff --git a/src/test/ui/proc-macro/proc-macro-gates.rs b/src/test/ui/proc-macro/proc-macro-gates.rs index 0096a84f14c34..678dc83b753b5 100644 --- a/src/test/ui/proc-macro/proc-macro-gates.rs +++ b/src/test/ui/proc-macro/proc-macro-gates.rs @@ -50,6 +50,7 @@ fn attrs() { } fn main() { + let _x: identity!(u32) = 3; //~ ERROR: procedural macros cannot be expanded to types if let identity!(Some(_x)) = Some(3) {} //~^ ERROR: procedural macros cannot be expanded to patterns diff --git a/src/test/ui/proc-macro/proc-macro-gates.stderr b/src/test/ui/proc-macro/proc-macro-gates.stderr index 14a4f8c0fbca2..8462b564ec1d7 100644 --- a/src/test/ui/proc-macro/proc-macro-gates.stderr +++ b/src/test/ui/proc-macro/proc-macro-gates.stderr @@ -94,8 +94,17 @@ LL | let _x = #[identity_attr] println!(); = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable +error[E0658]: procedural macros cannot be expanded to types + --> $DIR/proc-macro-gates.rs:53:13 + | +LL | let _x: identity!(u32) = 3; + | ^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54727 + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + error[E0658]: procedural macros cannot be expanded to patterns - --> $DIR/proc-macro-gates.rs:53:12 + --> $DIR/proc-macro-gates.rs:54:12 | LL | if let identity!(Some(_x)) = Some(3) {} | ^^^^^^^^^^^^^^^^^^^ @@ -104,7 +113,7 @@ LL | if let identity!(Some(_x)) = Some(3) {} = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable error[E0658]: procedural macros cannot be expanded to statements - --> $DIR/proc-macro-gates.rs:56:5 + --> $DIR/proc-macro-gates.rs:57:5 | LL | empty!(struct S;); | ^^^^^^^^^^^^^^^^^^ @@ -113,7 +122,7 @@ LL | empty!(struct S;); = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable error[E0658]: procedural macros cannot be expanded to statements - --> $DIR/proc-macro-gates.rs:57:5 + --> $DIR/proc-macro-gates.rs:58:5 | LL | empty!(let _x = 3;); | ^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +131,7 @@ LL | empty!(let _x = 3;); = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable error[E0658]: procedural macros cannot be expanded to expressions - --> $DIR/proc-macro-gates.rs:59:14 + --> $DIR/proc-macro-gates.rs:60:14 | LL | let _x = identity!(3); | ^^^^^^^^^^^^ @@ -131,7 +140,7 @@ LL | let _x = identity!(3); = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable error[E0658]: procedural macros cannot be expanded to expressions - --> $DIR/proc-macro-gates.rs:60:15 + --> $DIR/proc-macro-gates.rs:61:15 | LL | let _x = [empty!(3)]; | ^^^^^^^^^ @@ -139,6 +148,6 @@ LL | let _x = [empty!(3)]; = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable -error: aborting due to 16 previous errors +error: aborting due to 17 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/qualified/qualified-path-params.stderr b/src/test/ui/qualified/qualified-path-params.stderr index 3e8fcdc7ca3e2..b8d3b744e837c 100644 --- a/src/test/ui/qualified/qualified-path-params.stderr +++ b/src/test/ui/qualified/qualified-path-params.stderr @@ -15,5 +15,4 @@ LL | 0 ..= ::A::f:: => {} error: aborting due to 2 previous errors -Some errors have detailed explanations: E0029, E0533. -For more information about an error, try `rustc --explain E0029`. +For more information about this error, try `rustc --explain E0029`. diff --git a/src/test/ui/reachable-unnameable-items.rs b/src/test/ui/reachable-unnameable-items.rs index 26c51efea1e1c..f1e53a0d8b426 100644 --- a/src/test/ui/reachable-unnameable-items.rs +++ b/src/test/ui/reachable-unnameable-items.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // aux-build:reachable-unnameable-items.rs extern crate reachable_unnameable_items; 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 f9ae75b18317d..b9385952fafa3 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -3,13 +3,6 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered | LL | let Ok(x) = res; | ^^^^^ pattern `Err(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let Ok(x) = res { /* */ } - | error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/recursive-types-are-not-uninhabited.rs:8:5 diff --git a/src/test/ui/refutable-pattern-errors.stderr b/src/test/ui/refutable-pattern-errors.stderr index 0cf5d9cd5f12a..3b13e25293d58 100644 --- a/src/test/ui/refutable-pattern-errors.stderr +++ b/src/test/ui/refutable-pattern-errors.stderr @@ -9,13 +9,6 @@ error[E0005]: refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` an | LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)); | ^^^^^^^^^^^^^^^^^^^^^ patterns `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { /* */ } - | error: aborting due to 2 previous errors diff --git a/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr index 184cead21231f..003dd0699d381 100644 --- a/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr +++ b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr @@ -10,12 +10,12 @@ error[E0478]: lifetime bound not satisfied LL | z: Box+'b+'c>, | ^^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'b` as defined on the struct at 11:15 +note: lifetime parameter instantiated with the lifetime 'b as defined on the struct at 11:15 --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:15 | LL | struct Foo<'a,'b,'c> { | ^^ -note: but lifetime parameter must outlive the lifetime `'a` as defined on the struct at 11:12 +note: but lifetime parameter must outlive the lifetime 'a as defined on the struct at 11:12 --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:12 | LL | struct Foo<'a,'b,'c> { @@ -27,7 +27,7 @@ error[E0392]: parameter `'c` is never used LL | struct Foo<'a,'b,'c> { | ^^ unused parameter | - = help: consider removing `'c`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `'c` or using a marker such as `std::marker::PhantomData` error: aborting due to 3 previous errors diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.rs b/src/test/ui/regions/region-invariant-static-error-reporting.rs index 911904813d0eb..df92ed51e9a91 100644 --- a/src/test/ui/regions/region-invariant-static-error-reporting.rs +++ b/src/test/ui/regions/region-invariant-static-error-reporting.rs @@ -3,7 +3,7 @@ // over time, but this test used to exhibit some pretty bogus messages // that were not remotely helpful. -// error-pattern:the lifetime `'a` +// error-pattern:the lifetime 'a // error-pattern:the static lifetime struct Invariant<'a>(Option<&'a mut &'a mut ()>); diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.stderr b/src/test/ui/regions/region-invariant-static-error-reporting.stderr index 8358a7988c808..60e70ddcd9701 100644 --- a/src/test/ui/regions/region-invariant-static-error-reporting.stderr +++ b/src/test/ui/regions/region-invariant-static-error-reporting.stderr @@ -13,7 +13,7 @@ LL | | }; | = note: expected type `Invariant<'a>` found type `Invariant<'static>` -note: the lifetime `'a` as defined on the function body at 13:10... +note: the lifetime 'a as defined on the function body at 13:10... --> $DIR/region-invariant-static-error-reporting.rs:13:10 | LL | fn unify<'a>(x: Option>, f: fn(Invariant<'a>)) { diff --git a/src/test/ui/regions/region-object-lifetime-2.stderr b/src/test/ui/regions/region-object-lifetime-2.stderr index 74ea1b731e9ac..0c5e22ebae283 100644 --- a/src/test/ui/regions/region-object-lifetime-2.stderr +++ b/src/test/ui/regions/region-object-lifetime-2.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for autoref due to conflictin LL | x.borrowed() | ^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:42... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:42... --> $DIR/region-object-lifetime-2.rs:9:42 | LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | x.borrowed() | ^ -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 9:45... +note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 9:45... --> $DIR/region-object-lifetime-2.rs:9:45 | LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { @@ -27,4 +27,3 @@ LL | x.borrowed() error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/region-object-lifetime-4.stderr b/src/test/ui/regions/region-object-lifetime-4.stderr index 1053218290588..e737d27d5606f 100644 --- a/src/test/ui/regions/region-object-lifetime-4.stderr +++ b/src/test/ui/regions/region-object-lifetime-4.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for autoref due to conflictin LL | x.borrowed() | ^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 11:41... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 11:41... --> $DIR/region-object-lifetime-4.rs:11:41 | LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | x.borrowed() | ^ -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 11:44... +note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 11:44... --> $DIR/region-object-lifetime-4.rs:11:44 | LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () { @@ -27,4 +27,3 @@ LL | x.borrowed() error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 14934d6fa4899..8209fa1840d05 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -29,7 +29,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | Box::new(v) | ^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 25:6... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 25:6... --> $DIR/region-object-lifetime-in-coercion.rs:25:6 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { @@ -37,7 +37,7 @@ LL | fn d<'a,'b>(v: &'a [u8]) -> Box { = note: ...so that the expression is assignable: expected &[u8] found &'a [u8] -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 25:9... +note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 25:9... --> $DIR/region-object-lifetime-in-coercion.rs:25:9 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { @@ -48,5 +48,4 @@ LL | fn d<'a,'b>(v: &'a [u8]) -> Box { error: aborting due to 4 previous errors -Some errors have detailed explanations: E0495, E0621. -For more information about an error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/regions/regions-addr-of-self.stderr b/src/test/ui/regions/regions-addr-of-self.stderr index a0b8b6b51e5a1..2274e9341dbc9 100644 --- a/src/test/ui/regions/regions-addr-of-self.stderr +++ b/src/test/ui/regions/regions-addr-of-self.stderr @@ -26,4 +26,3 @@ LL | let p: &'static mut usize = &mut self.cats_chased; error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.stderr b/src/test/ui/regions/regions-addr-of-upvar-self.stderr index 7a051b8ac835d..d02caeb44f1a8 100644 --- a/src/test/ui/regions/regions-addr-of-upvar-self.stderr +++ b/src/test/ui/regions/regions-addr-of-upvar-self.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | let p: &'static mut usize = &mut self.food; | ^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 9:18... +note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 9:18... --> $DIR/regions-addr-of-upvar-self.rs:9:18 | LL | let _f = || { @@ -23,4 +23,3 @@ LL | let p: &'static mut usize = &mut self.food; error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. 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 c0401780b8f5b..61be0778c99c5 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 @@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifet LL | let _: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 33: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 33: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-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr index a636c9ef22c83..9732cd12ce15f 100644 --- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | impl<'a> Foo<'static> for &'a i32 { | ^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 14:6... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 14:6... --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:6 | LL | impl<'a> Foo<'static> for &'a i32 { @@ -25,7 +25,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | impl<'a,'b> Foo<'b> for &'a i64 { | ^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 19:6... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 19:6... --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:6 | LL | impl<'a,'b> Foo<'b> for &'a i64 { @@ -33,7 +33,7 @@ LL | impl<'a,'b> Foo<'b> for &'a i64 { = note: ...so that the types are compatible: expected Foo<'b> found Foo<'_> -note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 19:9... +note: but, the lifetime must be valid for the lifetime 'b as defined on the impl at 19:9... --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:9 | LL | impl<'a,'b> Foo<'b> for &'a i64 { @@ -46,4 +46,3 @@ LL | impl<'a,'b> Foo<'b> for &'a i64 { error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr index 81256e3b46cbb..2067bc3946c92 100644 --- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | impl<'a> Foo for &'a i32 { | ^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 9:6... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 9:6... --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:6 | LL | impl<'a> Foo for &'a i32 { @@ -21,4 +21,3 @@ LL | impl<'a> Foo for &'a i32 { error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-bounds.stderr b/src/test/ui/regions/regions-bounds.stderr index a15710b86c06e..27eb8891c6c06 100644 --- a/src/test/ui/regions/regions-bounds.stderr +++ b/src/test/ui/regions/regions-bounds.stderr @@ -6,12 +6,12 @@ LL | return e; | = note: expected type `TupleStruct<'b>` found type `TupleStruct<'a>` -note: the lifetime `'a` as defined on the function body at 8:10... +note: the lifetime 'a as defined on the function body at 8:10... --> $DIR/regions-bounds.rs:8:10 | LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 8:13 +note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 8:13 --> $DIR/regions-bounds.rs:8:13 | LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { @@ -25,12 +25,12 @@ LL | return e; | = note: expected type `Struct<'b>` found type `Struct<'a>` -note: the lifetime `'a` as defined on the function body at 12:10... +note: the lifetime 'a as defined on the function body at 12:10... --> $DIR/regions-bounds.rs:12:10 | LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 12:13 +note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 12:13 --> $DIR/regions-bounds.rs:12:13 | LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 8e473dad69341..fa203debb3a1b 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | box B(&*v) as Box | ^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:6... --> $DIR/regions-close-object-into-object-2.rs:9:6 | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { @@ -21,4 +21,3 @@ LL | box B(&*v) as Box error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index c80d13e15b147..f5e66f84a9ee7 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | box B(&*v) as Box | ^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:6... --> $DIR/regions-close-object-into-object-4.rs:9:6 | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { @@ -21,4 +21,3 @@ LL | box B(&*v) as Box error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr index ef21316ea83ae..8b3dbc8b64902 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr +++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | box v as Box | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 18:20... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 18:20... --> $DIR/regions-close-over-type-parameter-multiple.rs:18:20 | LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box { @@ -14,7 +14,7 @@ note: ...so that the declared lifetime parameter bounds are satisfied | LL | box v as Box | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: but, the lifetime must be valid for the lifetime `'c` as defined on the function body at 18:26... +note: but, the lifetime must be valid for the lifetime 'c as defined on the function body at 18:26... --> $DIR/regions-close-over-type-parameter-multiple.rs:18:26 | LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box { @@ -25,4 +25,3 @@ LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box $DIR/regions-creating-enums4.rs:6:16 | LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { @@ -12,7 +12,7 @@ LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { = note: ...so that the expression is assignable: expected &Ast<'_> found &Ast<'a> -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 6:19... +note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 6:19... --> $DIR/regions-creating-enums4.rs:6:19 | LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { @@ -23,4 +23,3 @@ LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. 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 9095451da0522..7b9f2c9503b2f 100644 --- a/src/test/ui/regions/regions-early-bound-error-method.stderr +++ b/src/test/ui/regions/regions-early-bound-error-method.stderr @@ -4,12 +4,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | g2.get() | ^^^^^^^^ | -note: ...the reference is valid for the lifetime `'a` as defined on the impl at 18:6... +note: ...the reference is valid for the lifetime 'a as defined on the impl at 18:6... --> $DIR/regions-early-bound-error-method.rs:18:6 | LL | impl<'a> Box<'a> { | ^^ -note: ...but the borrowed content is only valid for the lifetime `'b` as defined on the method body at 19:11 +note: ...but the borrowed content is only valid for the lifetime 'b as defined on the method body at 19:11 --> $DIR/regions-early-bound-error-method.rs:19:11 | LL | fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize { diff --git a/src/test/ui/regions/regions-early-bound-error.stderr b/src/test/ui/regions/regions-early-bound-error.stderr index 162d573362d45..a68355b78f54c 100644 --- a/src/test/ui/regions/regions-early-bound-error.stderr +++ b/src/test/ui/regions/regions-early-bound-error.stderr @@ -4,12 +4,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | g1.get() | ^^^^^^^^ | -note: ...the reference is valid for the lifetime `'b` as defined on the function body at 18:11... +note: ...the reference is valid for the lifetime 'b as defined on the function body at 18:11... --> $DIR/regions-early-bound-error.rs:18:11 | LL | fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize { | ^^ -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 18:8 +note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 18:8 --> $DIR/regions-early-bound-error.rs:18:8 | LL | fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize { diff --git a/src/test/ui/regions/regions-escape-method.stderr b/src/test/ui/regions/regions-escape-method.stderr index b93dd0d4c57c9..d867448e1372a 100644 --- a/src/test/ui/regions/regions-escape-method.stderr +++ b/src/test/ui/regions/regions-escape-method.stderr @@ -25,4 +25,3 @@ LL | s.f(|p| p) error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-escape-via-trait-or-not.stderr b/src/test/ui/regions/regions-escape-via-trait-or-not.stderr index a6b165e2d4444..c8a02683d1000 100644 --- a/src/test/ui/regions/regions-escape-via-trait-or-not.stderr +++ b/src/test/ui/regions/regions-escape-via-trait-or-not.stderr @@ -25,4 +25,3 @@ LL | with(|o| o) error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr b/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr index ad555efadf7ec..3b8f09f1ad80a 100644 --- a/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr @@ -8,12 +8,12 @@ LL | | let z: Option<&'a &'b usize> = None; LL | | } | |_^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 5:14 +note: the pointer is valid for the lifetime 'a as defined on the function body at 5:14 --> $DIR/regions-free-region-ordering-callee-4.rs:5:14 | LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 5:18 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 5:18 --> $DIR/regions-free-region-ordering-callee-4.rs:5:18 | LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) { diff --git a/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr index 10644174b9bc4..5fad6de2a62af 100644 --- a/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | None => &self.val | ^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the method body at 14:12... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the method body at 14:12... --> $DIR/regions-free-region-ordering-incorrect.rs:14:12 | LL | fn get<'a>(&'a self) -> &'b T { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | None => &self.val | ^^^^^^^^^ -note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 13:6... +note: but, the lifetime must be valid for the lifetime 'b as defined on the impl at 13:6... --> $DIR/regions-free-region-ordering-incorrect.rs:13:6 | LL | impl<'b, T> Node<'b, T> { @@ -30,4 +30,3 @@ LL | | } error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr index c4ca7e970749c..b3390bcc4d50b 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr @@ -7,12 +7,12 @@ LL | | { LL | | } | |_^ | -note: the pointer is valid for the lifetime `'x` as defined on the function body at 21:11 +note: the pointer is valid for the lifetime 'x as defined on the function body at 21:11 --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:11 | LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) | ^^ -note: but the referenced data is only valid for the lifetime `'y` as defined on the function body at 21:15 +note: but the referenced data is only valid for the lifetime 'y as defined on the function body at 21:15 --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:15 | LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) diff --git a/src/test/ui/regions/regions-infer-call-3.stderr b/src/test/ui/regions/regions-infer-call-3.stderr index 1d6dbdb2c7b57..151c8307a14f6 100644 --- a/src/test/ui/regions/regions-infer-call-3.stderr +++ b/src/test/ui/regions/regions-infer-call-3.stderr @@ -27,4 +27,3 @@ LL | let z = with(|y| { select(x, y) }); error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr index f4e223bbf6f9b..d31ed3ede36fa 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr @@ -6,7 +6,7 @@ LL | b_isize | = note: expected type `Invariant<'static>` found type `Invariant<'r>` -note: the lifetime `'r` as defined on the function body at 11:23... +note: the lifetime 'r as defined on the function body at 11:23... --> $DIR/regions-infer-invariance-due-to-decl.rs:11:23 | LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr index 6322244fcf937..f8bdd014db7c6 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr @@ -6,7 +6,7 @@ LL | b_isize | = note: expected type `Invariant<'static>` found type `Invariant<'r>` -note: the lifetime `'r` as defined on the function body at 9:23... +note: the lifetime 'r as defined on the function body at 9:23... --> $DIR/regions-infer-invariance-due-to-mutability-3.rs:9:23 | LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr index 7baae69945f9c..1de6f22f08e50 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr @@ -6,7 +6,7 @@ LL | b_isize | = note: expected type `Invariant<'static>` found type `Invariant<'r>` -note: the lifetime `'r` as defined on the function body at 9:23... +note: the lifetime 'r as defined on the function body at 9:23... --> $DIR/regions-infer-invariance-due-to-mutability-4.rs:9:23 | LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { diff --git a/src/test/ui/regions/regions-infer-not-param.stderr b/src/test/ui/regions/regions-infer-not-param.stderr index 6365769430f36..f43ab82912187 100644 --- a/src/test/ui/regions/regions-infer-not-param.stderr +++ b/src/test/ui/regions/regions-infer-not-param.stderr @@ -6,12 +6,12 @@ LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } | = note: expected type `Direct<'b>` found type `Direct<'a>` -note: the lifetime `'a` as defined on the function body at 15:16... +note: the lifetime 'a as defined on the function body at 15:16... --> $DIR/regions-infer-not-param.rs:15:16 | LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 15:19 +note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 15:19 --> $DIR/regions-infer-not-param.rs:15:19 | LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } @@ -25,12 +25,12 @@ LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } | = note: expected type `Indirect2<'b>` found type `Indirect2<'a>` -note: the lifetime `'a` as defined on the function body at 19:19... +note: the lifetime 'a as defined on the function body at 19:19... --> $DIR/regions-infer-not-param.rs:19:19 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 19:22 +note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 19:22 --> $DIR/regions-infer-not-param.rs:19:22 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } @@ -44,12 +44,12 @@ LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } | = note: expected type `Indirect2<'b>` found type `Indirect2<'a>` -note: the lifetime `'b` as defined on the function body at 19:22... +note: the lifetime 'b as defined on the function body at 19:22... --> $DIR/regions-infer-not-param.rs:19:22 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } | ^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the function body at 19:19 +note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 19:19 --> $DIR/regions-infer-not-param.rs:19:19 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } diff --git a/src/test/ui/regions/regions-infer-paramd-indirect.stderr b/src/test/ui/regions/regions-infer-paramd-indirect.stderr index b1fd337b8d04b..1b999ed059c40 100644 --- a/src/test/ui/regions/regions-infer-paramd-indirect.stderr +++ b/src/test/ui/regions/regions-infer-paramd-indirect.stderr @@ -17,7 +17,7 @@ LL | | LL | | LL | | } | |_____^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 16:6 +note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 16:6 --> $DIR/regions-infer-paramd-indirect.rs:16:6 | LL | impl<'a> SetF<'a> for C<'a> { diff --git a/src/test/ui/regions/regions-nested-fns.stderr b/src/test/ui/regions/regions-nested-fns.stderr index f4eb5c8644f03..904dee6998c9b 100644 --- a/src/test/ui/regions/regions-nested-fns.stderr +++ b/src/test/ui/regions/regions-nested-fns.stderr @@ -49,7 +49,7 @@ LL | | if false { return ay; } LL | | return z; LL | | })); | |_____^ -note: ...but the borrowed content is only valid for the lifetime `'x` as defined on the function body at 3:11 +note: ...but the borrowed content is only valid for the lifetime 'x as defined on the function body at 3:11 --> $DIR/regions-nested-fns.rs:3:11 | LL | fn nested<'x>(x: &'x isize) { @@ -57,5 +57,4 @@ LL | fn nested<'x>(x: &'x isize) { error: aborting due to 2 previous errors -Some errors have detailed explanations: E0312, E0495. -For more information about an error, try `rustc --explain E0312`. +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr index d29fd80943f73..912e118316271 100644 --- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr +++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr @@ -7,12 +7,12 @@ LL | | { LL | | } | |_^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 22:8... --> $DIR/regions-normalize-in-where-clause-list.rs:22:8 | LL | fn bar<'a, 'b>() | ^^ -note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12... +note: ...but the lifetime must also be valid for the lifetime 'b as defined on the function body at 22:12... --> $DIR/regions-normalize-in-where-clause-list.rs:22:12 | LL | fn bar<'a, 'b>() @@ -23,4 +23,3 @@ LL | fn bar<'a, 'b>() error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. 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 0992d9bf295c1..ed5800940ee31 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 @@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithHrAssoc>`, reference has a longer lif LL | let _: &'a WithHrAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 27: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 27: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>() { @@ -21,12 +21,12 @@ error[E0491]: in type `&'a WithHrAssocSub>`, reference has a longer LL | let _: &'a WithHrAssocSub> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 46: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 46: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-wc.migrate.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr index 49e28a14d8a4e..152e6c5600c4e 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 @@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifet LL | let _: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 27: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 27: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.stderr b/src/test/ui/regions/regions-outlives-projection-container.stderr index dba15fb0576ee..3c1a98a3c018f 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifet LL | let _x: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 28: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 28: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>() { @@ -21,12 +21,12 @@ error[E0491]: in type `&'a WithoutAssoc>`, reference has a longer li LL | let _x: &'a WithoutAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 50: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 50: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>() { @@ -38,12 +38,12 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifet LL | call::<&'a WithAssoc>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 58: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 58: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>() { @@ -55,12 +55,12 @@ error[E0491]: in type `&'a WithoutAssoc>`, reference has a longer li LL | call::<&'a WithoutAssoc>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 67: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 67: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-ret-borrowed-1.stderr b/src/test/ui/regions/regions-ret-borrowed-1.stderr index 49076673ad398..403af2a9e6a44 100644 --- a/src/test/ui/regions/regions-ret-borrowed-1.stderr +++ b/src/test/ui/regions/regions-ret-borrowed-1.stderr @@ -12,7 +12,7 @@ LL | with(|o| o) = note: ...so that the expression is assignable: expected &isize found &isize -note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 9:14... +note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 9:14... --> $DIR/regions-ret-borrowed-1.rs:9:14 | LL | fn return_it<'a>() -> &'a isize { @@ -25,4 +25,3 @@ LL | with(|o| o) error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-ret-borrowed.stderr b/src/test/ui/regions/regions-ret-borrowed.stderr index eb1ade27acea7..5d1f26da6c783 100644 --- a/src/test/ui/regions/regions-ret-borrowed.stderr +++ b/src/test/ui/regions/regions-ret-borrowed.stderr @@ -12,7 +12,7 @@ LL | with(|o| o) = note: ...so that the expression is assignable: expected &isize found &isize -note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 12:14... +note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 12:14... --> $DIR/regions-ret-borrowed.rs:12:14 | LL | fn return_it<'a>() -> &'a isize { @@ -25,4 +25,3 @@ LL | with(|o| o) error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr index 946465bcb5f26..291b8367f7b75 100644 --- a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr +++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | let mut f = || &mut x; | ^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 7:21... +note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 7:21... --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:21 | LL | let mut f = || &mut x; @@ -27,4 +27,3 @@ LL | let y = f(); error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-static-bound.migrate.stderr b/src/test/ui/regions/regions-static-bound.migrate.stderr index 6e631d40d4500..21ead8b768f47 100644 --- a/src/test/ui/regions/regions-static-bound.migrate.stderr +++ b/src/test/ui/regions/regions-static-bound.migrate.stderr @@ -5,7 +5,7 @@ LL | t | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 8:24 +note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 8:24 --> $DIR/regions-static-bound.rs:8:24 | LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { diff --git a/src/test/ui/regions/regions-trait-1.stderr b/src/test/ui/regions/regions-trait-1.stderr index f835c005ff969..421f826ccc54e 100644 --- a/src/test/ui/regions/regions-trait-1.stderr +++ b/src/test/ui/regions/regions-trait-1.stderr @@ -6,7 +6,7 @@ LL | fn get_ctxt(&self) -> &'a Ctxt { | = note: expected type `fn(&HasCtxt<'a>) -> &Ctxt` found type `fn(&HasCtxt<'a>) -> &'a Ctxt` -note: the lifetime `'a` as defined on the impl at 12:6... +note: the lifetime 'a as defined on the impl at 12:6... --> $DIR/regions-trait-1.rs:12:6 | LL | impl<'a> GetCtxt for HasCtxt<'a> { diff --git a/src/test/ui/regions/regions-trait-object-subtyping.stderr b/src/test/ui/regions/regions-trait-object-subtyping.stderr index b7c7f93149dcf..6de92f13840b3 100644 --- a/src/test/ui/regions/regions-trait-object-subtyping.stderr +++ b/src/test/ui/regions/regions-trait-object-subtyping.stderr @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied LL | x | ^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the function body at 13:9 +note: lifetime parameter instantiated with the lifetime 'a as defined on the function body at 13:9 --> $DIR/regions-trait-object-subtyping.rs:13:9 | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { | ^^ -note: but lifetime parameter must outlive the lifetime `'b` as defined on the function body at 13:12 +note: but lifetime parameter must outlive the lifetime 'b as defined on the function body at 13:12 --> $DIR/regions-trait-object-subtyping.rs:13:12 | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { @@ -21,7 +21,7 @@ error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to LL | x | ^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 13:9... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 13:9... --> $DIR/regions-trait-object-subtyping.rs:13:9 | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { @@ -31,7 +31,7 @@ note: ...so that reference does not outlive borrowed content | LL | x | ^ -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 13:12... +note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 13:12... --> $DIR/regions-trait-object-subtyping.rs:13:12 | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { @@ -48,12 +48,12 @@ LL | x | = note: expected type `Wrapper<&'b mut (dyn Dummy + 'b)>` found type `Wrapper<&'a mut (dyn Dummy + 'a)>` -note: the lifetime `'b` as defined on the function body at 20:15... +note: the lifetime 'b as defined on the function body at 20:15... --> $DIR/regions-trait-object-subtyping.rs:20:15 | LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> { | ^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the function body at 20:9 +note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 20:9 --> $DIR/regions-trait-object-subtyping.rs:20:9 | LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> { @@ -61,5 +61,5 @@ LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dum error: aborting due to 3 previous errors -Some errors have detailed explanations: E0308, E0478, E0495. +Some errors have detailed explanations: E0308, E0478. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr b/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr index aae519c5df2e9..90b37ce935a6d 100644 --- a/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr +++ b/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr @@ -6,7 +6,7 @@ LL | let _: Invariant<'static> = c; | = note: expected type `Invariant<'static>` found type `Invariant<'b>` -note: the lifetime `'b` as defined on the function body at 11:9... +note: the lifetime 'b as defined on the function body at 11:9... --> $DIR/regions-variance-invariant-use-covariant.rs:11:9 | LL | fn use_<'b>(c: Invariant<'b>) { diff --git a/src/test/ui/regions/regions-wf-trait-object.stderr b/src/test/ui/regions/regions-wf-trait-object.stderr index 9f39508604110..4e12478c36da3 100644 --- a/src/test/ui/regions/regions-wf-trait-object.stderr +++ b/src/test/ui/regions/regions-wf-trait-object.stderr @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied LL | x: Box+'b> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'b` as defined on the struct at 6:15 +note: lifetime parameter instantiated with the lifetime 'b as defined on the struct at 6:15 --> $DIR/regions-wf-trait-object.rs:6:15 | LL | struct Foo<'a,'b> { | ^^ -note: but lifetime parameter must outlive the lifetime `'a` as defined on the struct at 6:12 +note: but lifetime parameter must outlive the lifetime 'a as defined on the struct at 6:12 --> $DIR/regions-wf-trait-object.rs:6:12 | LL | struct Foo<'a,'b> { diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index 609a40163a30c..08aca3bb14c26 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -34,7 +34,7 @@ LL | impl Drop for N<'static> { fn drop(&mut self) { } } | = note: expected type `N<'n>` found type `N<'static>` -note: the lifetime `'n` as defined on the struct at 8:10... +note: the lifetime 'n as defined on the struct at 8:10... --> $DIR/reject-specialized-drops-8142.rs:8:10 | LL | struct N<'n> { x: &'n i8 } @@ -95,12 +95,12 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'l1` as defined on the struct at 17:10... +note: first, the lifetime cannot outlive the lifetime 'l1 as defined on the struct at 17:10... --> $DIR/reject-specialized-drops-8142.rs:17:10 | LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } | ^^^ -note: ...but the lifetime must also be valid for the lifetime `'l2` as defined on the struct at 17:15... +note: ...but the lifetime must also be valid for the lifetime 'l2 as defined on the struct at 17:15... --> $DIR/reject-specialized-drops-8142.rs:17:15 | LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } @@ -111,5 +111,5 @@ LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } error: aborting due to 8 previous errors -Some errors have detailed explanations: E0308, E0366, E0367, E0495. +Some errors have detailed explanations: E0308, E0366, E0367. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/repr/repr-packed-contains-align.stderr b/src/test/ui/repr/repr-packed-contains-align.stderr index df001d6b5f2a4..219516d8abc48 100644 --- a/src/test/ui/repr/repr-packed-contains-align.stderr +++ b/src/test/ui/repr/repr-packed-contains-align.stderr @@ -56,4 +56,3 @@ LL | | } error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0588`. diff --git a/src/test/ui/resolve/issue-16058.stderr b/src/test/ui/resolve/issue-16058.stderr index 9766f8f1412b6..64177ac2a8310 100644 --- a/src/test/ui/resolve/issue-16058.stderr +++ b/src/test/ui/resolve/issue-16058.stderr @@ -14,4 +14,3 @@ LL | use std::thread::Result; error: aborting due to previous error -For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/resolve/issue-18252.stderr b/src/test/ui/resolve/issue-18252.stderr index c76e5ef8b3617..293f290f82fd9 100644 --- a/src/test/ui/resolve/issue-18252.stderr +++ b/src/test/ui/resolve/issue-18252.stderr @@ -1,9 +1,6 @@ error[E0423]: expected function, found struct variant `Foo::Variant` --> $DIR/issue-18252.rs:6:13 | -LL | Variant { x: usize } - | -------------------- `Foo::Variant` defined here -... LL | let f = Foo::Variant(42); | ^^^^^^^^^^^^ did you mean `Foo::Variant { /* fields */ }`? diff --git a/src/test/ui/resolve/issue-19452.stderr b/src/test/ui/resolve/issue-19452.stderr index 4d20f1580264c..56a0e397b854c 100644 --- a/src/test/ui/resolve/issue-19452.stderr +++ b/src/test/ui/resolve/issue-19452.stderr @@ -1,9 +1,6 @@ error[E0423]: expected value, found struct variant `Homura::Madoka` --> $DIR/issue-19452.rs:10:18 | -LL | Madoka { age: u32 } - | ------------------- `Homura::Madoka` defined here -... LL | let homura = Homura::Madoka; | ^^^^^^^^^^^^^^ did you mean `Homura::Madoka { /* fields */ }`? diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr index 513e02f74e3b2..d00d87393aab6 100644 --- a/src/test/ui/resolve/issue-21221-1.stderr +++ b/src/test/ui/resolve/issue-21221-1.stderr @@ -27,7 +27,7 @@ LL | use mul3::Mul; | LL | use mul4::Mul; | - and 2 other candidates +and 2 other candidates error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope --> $DIR/issue-21221-1.rs:63:6 diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index 329543114a610..7790383843e17 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -61,14 +61,8 @@ LL | purr(); error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:65:8 | -LL | / fn meow() { -LL | | if self.whiskers > 3 { - | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter -LL | | -LL | | println!("MEOW"); -LL | | } -LL | | } - | |___- this function doesn't have a `self` parameter +LL | if self.whiskers > 3 { + | ^^^^ `self` value is a keyword only available in methods with `self` parameter error[E0425]: cannot find function `grow_older` in this scope --> $DIR/issue-2356.rs:72:5 @@ -103,12 +97,8 @@ LL | purr_louder(); error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:92:5 | -LL | / fn main() { -LL | | self += 1; - | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter -LL | | -LL | | } - | |_- this function doesn't have a `self` parameter +LL | self += 1; + | ^^^^ `self` value is a keyword only available in methods with `self` parameter error: aborting due to 17 previous errors diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr index d9a28e63dce8b..c97fb4db6be6b 100644 --- a/src/test/ui/resolve/issue-39226.stderr +++ b/src/test/ui/resolve/issue-39226.stderr @@ -1,9 +1,6 @@ error[E0423]: expected value, found struct `Handle` --> $DIR/issue-39226.rs:11:17 | -LL | struct Handle {} - | ---------------- `Handle` defined here -... LL | handle: Handle | ^^^^^^ | | diff --git a/src/test/ui/resolve/issue-65025-extern-static-parent-generics.rs b/src/test/ui/resolve/issue-65025-extern-static-parent-generics.rs deleted file mode 100644 index ce45f630e48a5..0000000000000 --- a/src/test/ui/resolve/issue-65025-extern-static-parent-generics.rs +++ /dev/null @@ -1,10 +0,0 @@ -unsafe fn foo() { - extern "C" { - static baz: *const A; - //~^ ERROR can't use generic parameters from outer function - } - - let bar: *const u64 = core::mem::transmute(&baz); -} - -fn main() { } diff --git a/src/test/ui/resolve/issue-65025-extern-static-parent-generics.stderr b/src/test/ui/resolve/issue-65025-extern-static-parent-generics.stderr deleted file mode 100644 index 6bbf76dd1fbb2..0000000000000 --- a/src/test/ui/resolve/issue-65025-extern-static-parent-generics.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0401]: can't use generic parameters from outer function - --> $DIR/issue-65025-extern-static-parent-generics.rs:3:28 - | -LL | unsafe fn foo() { - | - type parameter from outer function -LL | extern "C" { -LL | static baz: *const A; - | ^ use of generic parameter from outer function - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0401`. diff --git a/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs b/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs deleted file mode 100644 index 63d3431ec9b2f..0000000000000 --- a/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs +++ /dev/null @@ -1,29 +0,0 @@ -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -fn f() { - extern "C" { - static a: *const T; - //~^ ERROR can't use generic parameters from outer function - } -} - -fn g() { - static a: *const T = Default::default(); - //~^ ERROR can't use generic parameters from outer function -} - -fn h() { - extern "C" { - static a: [u8; N]; - //~^ ERROR can't use generic parameters from outer function - } -} - -fn i() { - static a: [u8; N] = [0; N]; - //~^ ERROR can't use generic parameters from outer function - //~^^ ERROR can't use generic parameters from outer function -} - -fn main() {} diff --git a/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr b/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr deleted file mode 100644 index 82e2aa2db8e25..0000000000000 --- a/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr +++ /dev/null @@ -1,53 +0,0 @@ -error[E0401]: can't use generic parameters from outer function - --> $DIR/issue-65035-static-with-parent-generics.rs:6:26 - | -LL | fn f() { - | - type parameter from outer function -LL | extern "C" { -LL | static a: *const T; - | ^ use of generic parameter from outer function - -error[E0401]: can't use generic parameters from outer function - --> $DIR/issue-65035-static-with-parent-generics.rs:12:22 - | -LL | fn g() { - | - type parameter from outer function -LL | static a: *const T = Default::default(); - | ^ use of generic parameter from outer function - -error[E0401]: can't use generic parameters from outer function - --> $DIR/issue-65035-static-with-parent-generics.rs:18:24 - | -LL | fn h() { - | - const parameter from outer function -LL | extern "C" { -LL | static a: [u8; N]; - | ^ use of generic parameter from outer function - -error[E0401]: can't use generic parameters from outer function - --> $DIR/issue-65035-static-with-parent-generics.rs:24:20 - | -LL | fn i() { - | - const parameter from outer function -LL | static a: [u8; N] = [0; N]; - | ^ use of generic parameter from outer function - -error[E0401]: can't use generic parameters from outer function - --> $DIR/issue-65035-static-with-parent-generics.rs:24:29 - | -LL | fn i() { - | - const parameter from outer function -LL | static a: [u8; N] = [0; N]; - | ^ use of generic parameter from outer function - -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/issue-65035-static-with-parent-generics.rs:1:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0401`. diff --git a/src/test/ui/resolve/issue-6702.stderr b/src/test/ui/resolve/issue-6702.stderr index 3fdc7acb274e5..9a46f0d774262 100644 --- a/src/test/ui/resolve/issue-6702.stderr +++ b/src/test/ui/resolve/issue-6702.stderr @@ -1,13 +1,8 @@ error[E0423]: expected function, found struct `Monster` --> $DIR/issue-6702.rs:7:14 | -LL | / struct Monster { -LL | | damage: isize -LL | | } - | |_- `Monster` defined here -... -LL | let _m = Monster(); - | ^^^^^^^ did you mean `Monster { /* fields */ }`? +LL | let _m = Monster(); + | ^^^^^^^ did you mean `Monster { /* fields */ }`? error: aborting due to previous error diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr index e693a0ef91fc2..2e3c0f5448e86 100644 --- a/src/test/ui/resolve/levenshtein.stderr +++ b/src/test/ui/resolve/levenshtein.stderr @@ -38,13 +38,13 @@ error[E0412]: cannot find type `first` in module `m` --> $DIR/levenshtein.rs:28:15 | LL | let b: m::first = m::second; // Misspelled item in module. - | ^^^^^ help: a struct with a similar name exists (notice the capitalization): `First` + | ^^^^^ help: a struct with a similar name exists: `First` error[E0425]: cannot find value `second` in module `m` --> $DIR/levenshtein.rs:28:26 | LL | let b: m::first = m::second; // Misspelled item in module. - | ^^^^^^ help: a unit struct with a similar name exists (notice the capitalization): `Second` + | ^^^^^^ help: a unit struct with a similar name exists: `Second` error: aborting due to 8 previous errors diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 7d8d1d0abfc21..2538bbbf8067f 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -33,13 +33,8 @@ LL | m::Z::Unit; error[E0423]: expected value, found struct variant `Z::Struct` --> $DIR/privacy-enum-ctor.rs:29:20 | -LL | / Struct { -LL | | s: u8, -LL | | }, - | |_____________- `Z::Struct` defined here -... -LL | let _: Z = Z::Struct; - | ^^^^^^^^^ did you mean `Z::Struct { /* fields */ }`? +LL | let _: Z = Z::Struct; + | ^^^^^^^^^ did you mean `Z::Struct { /* fields */ }`? error[E0423]: expected value, found enum `m::E` --> $DIR/privacy-enum-ctor.rs:41:16 @@ -68,13 +63,8 @@ LL | use std::f64::consts::E; error[E0423]: expected value, found struct variant `m::E::Struct` --> $DIR/privacy-enum-ctor.rs:45:16 | -LL | / Struct { -LL | | s: u8, -LL | | }, - | |_________- `m::E::Struct` defined here -... -LL | let _: E = m::E::Struct; - | ^^^^^^^^^^^^ did you mean `m::E::Struct { /* fields */ }`? +LL | let _: E = m::E::Struct; + | ^^^^^^^^^^^^ did you mean `m::E::Struct { /* fields */ }`? error[E0423]: expected value, found enum `E` --> $DIR/privacy-enum-ctor.rs:49:16 @@ -99,13 +89,8 @@ LL | use std::f64::consts::E; error[E0423]: expected value, found struct variant `E::Struct` --> $DIR/privacy-enum-ctor.rs:53:16 | -LL | / Struct { -LL | | s: u8, -LL | | }, - | |_________- `E::Struct` defined here -... -LL | let _: E = E::Struct; - | ^^^^^^^^^ did you mean `E::Struct { /* fields */ }`? +LL | let _: E = E::Struct; + | ^^^^^^^^^ did you mean `E::Struct { /* fields */ }`? error[E0412]: cannot find type `Z` in this scope --> $DIR/privacy-enum-ctor.rs:57:12 @@ -166,13 +151,8 @@ LL | use m::n::Z; error[E0423]: expected value, found struct variant `m::n::Z::Struct` --> $DIR/privacy-enum-ctor.rs:64:16 | -LL | / Struct { -LL | | s: u8, -LL | | }, - | |_____________- `m::n::Z::Struct` defined here -... -LL | let _: Z = m::n::Z::Struct; - | ^^^^^^^^^^^^^^^ did you mean `m::n::Z::Struct { /* fields */ }`? +LL | let _: Z = m::n::Z::Struct; + | ^^^^^^^^^^^^^^^ did you mean `m::n::Z::Struct { /* fields */ }`? error[E0412]: cannot find type `Z` in this scope --> $DIR/privacy-enum-ctor.rs:68:12 diff --git a/src/test/ui/resolve/privacy-struct-ctor.rs b/src/test/ui/resolve/privacy-struct-ctor.rs index 0eecc7f8cc5db..0b389acf75d8b 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.rs +++ b/src/test/ui/resolve/privacy-struct-ctor.rs @@ -16,7 +16,7 @@ mod m { fn f() { n::Z; - //~^ ERROR tuple struct constructor `Z` is private + //~^ ERROR tuple struct `Z` is private Z; //~^ ERROR expected value, found struct `Z` } @@ -27,21 +27,21 @@ use m::S2; // OK, only the type is imported fn main() { m::S; - //~^ ERROR tuple struct constructor `S` is private + //~^ ERROR tuple struct `S` is private let _: S = m::S(2); - //~^ ERROR tuple struct constructor `S` is private + //~^ ERROR tuple struct `S` is private S; //~^ ERROR expected value, found struct `S` m::n::Z; - //~^ ERROR tuple struct constructor `Z` is private + //~^ ERROR tuple struct `Z` is private S2; //~^ ERROR expected value, found struct `S2` xcrate::m::S; - //~^ ERROR tuple struct constructor `S` is private + //~^ ERROR tuple struct `S` is private xcrate::S; //~^ ERROR expected value, found struct `xcrate::S` xcrate::m::n::Z; - //~^ ERROR tuple struct constructor `Z` is private + //~^ ERROR tuple struct `Z` is private } diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index 7d884d3a66910..72d62fe45ce74 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -16,13 +16,8 @@ LL | S; error[E0423]: expected value, found struct `S2` --> $DIR/privacy-struct-ctor.rs:38:5 | -LL | / pub struct S2 { -LL | | s: u8 -LL | | } - | |_____- `S2` defined here -... -LL | S2; - | ^^ did you mean `S2 { /* fields */ }`? +LL | S2; + | ^^ did you mean `S2 { /* fields */ }`? error[E0423]: expected value, found struct `xcrate::S` --> $DIR/privacy-struct-ctor.rs:43:5 @@ -34,63 +29,53 @@ help: possible better candidate is found in another module, you can import it in LL | use m::S; | -error[E0603]: tuple struct constructor `Z` is private +error[E0603]: tuple struct `Z` is private --> $DIR/privacy-struct-ctor.rs:18:12 | -LL | pub(in m) struct Z(pub(in m::n) u8); - | --------------- a constructor is private if any of the fields is private -... LL | n::Z; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `S` is private +error[E0603]: tuple struct `S` is private --> $DIR/privacy-struct-ctor.rs:29:8 | -LL | pub struct S(u8); - | -- a constructor is private if any of the fields is private -... LL | m::S; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `S` is private +error[E0603]: tuple struct `S` is private --> $DIR/privacy-struct-ctor.rs:31:19 | -LL | pub struct S(u8); - | -- a constructor is private if any of the fields is private -... LL | let _: S = m::S(2); | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `Z` is private +error[E0603]: tuple struct `Z` is private --> $DIR/privacy-struct-ctor.rs:35:11 | -LL | pub(in m) struct Z(pub(in m::n) u8); - | --------------- a constructor is private if any of the fields is private -... LL | m::n::Z; | ^ + | + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `S` is private +error[E0603]: tuple struct `S` is private --> $DIR/privacy-struct-ctor.rs:41:16 | LL | xcrate::m::S; | ^ - | - ::: $DIR/auxiliary/privacy-struct-ctor.rs:2:18 | -LL | pub struct S(u8); - | -- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct constructor `Z` is private +error[E0603]: tuple struct `Z` is private --> $DIR/privacy-struct-ctor.rs:45:19 | LL | xcrate::m::n::Z; | ^ - | - ::: $DIR/auxiliary/privacy-struct-ctor.rs:5:28 | -LL | pub(in m) struct Z(pub(in m::n) u8); - | --------------- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private error: aborting due to 10 previous errors diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs index c8e8b9dcfc6a7..39825c4f9a938 100644 --- a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs @@ -1,8 +1,6 @@ // compile-flags: --test // run-pass -// ignore-emscripten compiled with panic=abort by default - #![feature(test)] extern crate test; diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs index bbc25d40256ff..e3820599c72d9 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs @@ -1,4 +1,5 @@ #![crate_type = "rlib"] +#![feature(non_exhaustive)] #[non_exhaustive] pub enum NonExhaustiveEnum { diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs index 6bfe7bf923d09..ddfb9ad003748 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs @@ -1,3 +1,5 @@ +#![feature(non_exhaustive)] + #[non_exhaustive] pub struct NormalStruct { pub first_field: u16, diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs index 02672d5454e57..f590d0a3268ff 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs @@ -1,4 +1,5 @@ #![crate_type = "rlib"] +#![feature(non_exhaustive)] pub enum NonExhaustiveVariants { #[non_exhaustive] Unit, diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate.rs index 54e42917f52d2..a3626bf60b260 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate.rs @@ -1,5 +1,7 @@ // run-pass +#![feature(non_exhaustive)] + #[non_exhaustive] pub enum NonExhaustiveEnum { Unit, diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs deleted file mode 100644 index d6251fcb768f4..0000000000000 --- a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs +++ /dev/null @@ -1,29 +0,0 @@ -#[non_exhaustive] -#[repr(C)] -pub enum NonExhaustiveEnum { - Unit, - Tuple(u32), - Struct { field: u32 } -} - -#[non_exhaustive] -#[repr(C)] -pub struct NormalStruct { - pub first_field: u16, - pub second_field: u16, -} - -#[non_exhaustive] -#[repr(C)] -pub struct UnitStruct; - -#[non_exhaustive] -#[repr(C)] -pub struct TupleStruct (pub u16, pub u16); - -#[repr(C)] -pub enum NonExhaustiveVariants { - #[non_exhaustive] Unit, - #[non_exhaustive] Tuple(u32), - #[non_exhaustive] Struct { field: u32 } -} diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs deleted file mode 100644 index 900b9333f76e8..0000000000000 --- a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs +++ /dev/null @@ -1,24 +0,0 @@ -// aux-build:types.rs -#![deny(improper_ctypes)] - -extern crate types; - -// This test checks that non-exhaustive types with `#[repr(C)]` from an extern crate are considered -// improper. - -use types::{NonExhaustiveEnum, NormalStruct, UnitStruct, TupleStruct, NonExhaustiveVariants}; - -extern { - pub fn non_exhaustive_enum(_: NonExhaustiveEnum); - //~^ ERROR `extern` block uses type `types::NonExhaustiveEnum`, which is not FFI-safe - pub fn non_exhaustive_normal_struct(_: NormalStruct); - //~^ ERROR `extern` block uses type `types::NormalStruct`, which is not FFI-safe - pub fn non_exhaustive_unit_struct(_: UnitStruct); - //~^ ERROR `extern` block uses type `types::UnitStruct`, which is not FFI-safe - pub fn non_exhaustive_tuple_struct(_: TupleStruct); - //~^ ERROR `extern` block uses type `types::TupleStruct`, which is not FFI-safe - pub fn non_exhaustive_variant(_: NonExhaustiveVariants); - //~^ ERROR `extern` block uses type `types::NonExhaustiveVariants`, which is not FFI-safe -} - -fn main() { } diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr deleted file mode 100644 index 7fbf1157e56f8..0000000000000 --- a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr +++ /dev/null @@ -1,47 +0,0 @@ -error: `extern` block uses type `types::NonExhaustiveEnum`, which is not FFI-safe - --> $DIR/extern_crate_improper.rs:12:35 - | -LL | pub fn non_exhaustive_enum(_: NonExhaustiveEnum); - | ^^^^^^^^^^^^^^^^^ not FFI-safe - | -note: lint level defined here - --> $DIR/extern_crate_improper.rs:2:9 - | -LL | #![deny(improper_ctypes)] - | ^^^^^^^^^^^^^^^ - = note: this enum is non-exhaustive - -error: `extern` block uses type `types::NormalStruct`, which is not FFI-safe - --> $DIR/extern_crate_improper.rs:14:44 - | -LL | pub fn non_exhaustive_normal_struct(_: NormalStruct); - | ^^^^^^^^^^^^ not FFI-safe - | - = note: this struct is non-exhaustive - -error: `extern` block uses type `types::UnitStruct`, which is not FFI-safe - --> $DIR/extern_crate_improper.rs:16:42 - | -LL | pub fn non_exhaustive_unit_struct(_: UnitStruct); - | ^^^^^^^^^^ not FFI-safe - | - = note: this struct is non-exhaustive - -error: `extern` block uses type `types::TupleStruct`, which is not FFI-safe - --> $DIR/extern_crate_improper.rs:18:43 - | -LL | pub fn non_exhaustive_tuple_struct(_: TupleStruct); - | ^^^^^^^^^^^ not FFI-safe - | - = note: this struct is non-exhaustive - -error: `extern` block uses type `types::NonExhaustiveVariants`, which is not FFI-safe - --> $DIR/extern_crate_improper.rs:20:38 - | -LL | pub fn non_exhaustive_variant(_: NonExhaustiveVariants); - | ^^^^^^^^^^^^^^^^^^^^^ not FFI-safe - | - = note: this enum has non-exhaustive variants - -error: aborting due to 5 previous errors - diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs deleted file mode 100644 index c09aa256e0e74..0000000000000 --- a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs +++ /dev/null @@ -1,45 +0,0 @@ -// check-pass -#![deny(improper_ctypes)] - -// This test checks that non-exhaustive types with `#[repr(C)]` are considered proper within -// the defining crate. - -#[non_exhaustive] -#[repr(C)] -pub enum NonExhaustiveEnum { - Unit, - Tuple(u32), - Struct { field: u32 } -} - -#[non_exhaustive] -#[repr(C)] -pub struct NormalStruct { - pub first_field: u16, - pub second_field: u16, -} - -#[non_exhaustive] -#[repr(C)] -pub struct UnitStruct; - -#[non_exhaustive] -#[repr(C)] -pub struct TupleStruct (pub u16, pub u16); - -#[repr(C)] -pub enum NonExhaustiveVariants { - #[non_exhaustive] Unit, - #[non_exhaustive] Tuple(u32), - #[non_exhaustive] Struct { field: u32 } -} - -extern { - // Unit structs aren't tested here because they will trigger `improper_ctypes` anyway. - pub fn non_exhaustive_enum(_: NonExhaustiveEnum); - pub fn non_exhaustive_normal_struct(_: NormalStruct); - pub fn non_exhaustive_tuple_struct(_: TupleStruct); - pub fn non_exhaustive_variant(_: NonExhaustiveVariants); -} - -fn main() { } diff --git a/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.rs b/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.rs index 3c4a09fafd2db..b7938e1afa3bc 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.rs @@ -1,3 +1,5 @@ +#![feature(non_exhaustive)] + #[non_exhaustive(anything)] //~^ ERROR malformed `non_exhaustive` attribute struct Foo; diff --git a/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr b/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr index 76d9e2d8205b7..21dc340d21204 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr @@ -1,11 +1,11 @@ error: malformed `non_exhaustive` attribute input - --> $DIR/invalid-attribute.rs:1:1 + --> $DIR/invalid-attribute.rs:3:1 | LL | #[non_exhaustive(anything)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[non_exhaustive]` error[E0701]: attribute can only be applied to a struct or enum - --> $DIR/invalid-attribute.rs:5:1 + --> $DIR/invalid-attribute.rs:7:1 | LL | #[non_exhaustive] | ^^^^^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL | trait Bar { } | ------------- not a struct or enum error[E0701]: attribute can only be applied to a struct or enum - --> $DIR/invalid-attribute.rs:9:1 + --> $DIR/invalid-attribute.rs:11:1 | LL | #[non_exhaustive] | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.rs b/src/test/ui/rfc-2008-non-exhaustive/struct.rs index cf383a260e044..94ac588d24083 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.rs @@ -21,7 +21,7 @@ fn main() { //~^ ERROR expected function, found struct `TupleStruct` [E0423] let ts_explicit = structs::TupleStruct(640, 480); - //~^ ERROR tuple struct constructor `TupleStruct` is private [E0603] + //~^ ERROR tuple struct `TupleStruct` is private [E0603] let TupleStruct { 0: first_field, 1: second_field } = ts; //~^ ERROR `..` required with struct marked as non-exhaustive diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index 04cfe51cab025..d75a376286fcc 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -10,16 +10,13 @@ error[E0423]: expected value, found struct `UnitStruct` LL | let us = UnitStruct; | ^^^^^^^^^^ constructor is not visible here due to private fields -error[E0603]: tuple struct constructor `TupleStruct` is private +error[E0603]: tuple struct `TupleStruct` is private --> $DIR/struct.rs:23:32 | LL | let ts_explicit = structs::TupleStruct(640, 480); | ^^^^^^^^^^^ - | - ::: $DIR/auxiliary/structs.rs:11:24 | -LL | pub struct TupleStruct(pub u16, pub u16); - | ---------------- a constructor is private if any of the fields is private + = note: a tuple struct constructor is private if any of its fields is private error[E0603]: unit struct `UnitStruct` is private --> $DIR/struct.rs:32:32 diff --git a/src/test/ui/rfc-2008-non-exhaustive/structs_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/structs_same_crate.rs index 5f76b0cb2f4b6..2b1d7d9ac5030 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/structs_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/structs_same_crate.rs @@ -1,6 +1,7 @@ // run-pass #![allow(unused_variables)] +#![feature(non_exhaustive)] #[non_exhaustive] pub struct NormalStruct { diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs index a2735d4cbfb29..8cb9a8cf1f613 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs @@ -1,5 +1,6 @@ #![crate_type = "rlib"] #![feature(never_type)] +#![feature(non_exhaustive)] #[non_exhaustive] pub enum UninhabitedEnum { diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs index 6b911dd989cc5..803a542f8aa4b 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs @@ -1,4 +1,5 @@ #![feature(never_type)] +#![feature(non_exhaustive)] #[non_exhaustive] pub enum UninhabitedEnum { diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr index a07473dade22c..8f6b709bb1f34 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/coercions_same_crate.rs:30:5 + --> $DIR/coercions_same_crate.rs:31:5 | LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { | - expected `A` because of return type @@ -10,7 +10,7 @@ LL | x found type `UninhabitedEnum` error[E0308]: mismatched types - --> $DIR/coercions_same_crate.rs:34:5 + --> $DIR/coercions_same_crate.rs:35:5 | LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { | - expected `A` because of return type @@ -21,7 +21,7 @@ LL | x found type `UninhabitedTupleStruct` error[E0308]: mismatched types - --> $DIR/coercions_same_crate.rs:38:5 + --> $DIR/coercions_same_crate.rs:39:5 | LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { | - expected `A` because of return type @@ -32,7 +32,7 @@ LL | x found type `UninhabitedStruct` error[E0308]: mismatched types - --> $DIR/coercions_same_crate.rs:42:5 + --> $DIR/coercions_same_crate.rs:43:5 | LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { | - expected `A` because of return type diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs index 8f090fe886a00..3c8d495e12cb6 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs @@ -1,4 +1,5 @@ #![feature(never_type)] +#![feature(non_exhaustive)] #[non_exhaustive] pub enum UninhabitedEnum { diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr index c03018a523647..27b120792d6d1 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedEnum` of type `IndirectUninhabitedEnum` is not handled - --> $DIR/indirect_match_same_crate.rs:34:11 + --> $DIR/indirect_match_same_crate.rs:35:11 | LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); | ---------------------------------------------------- @@ -13,7 +13,7 @@ LL | match x {} = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedStruct` of type `IndirectUninhabitedStruct` is not handled - --> $DIR/indirect_match_same_crate.rs:38:11 + --> $DIR/indirect_match_same_crate.rs:39:11 | LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); | -------------------------------------------------------- @@ -27,7 +27,7 @@ LL | match x {} = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedTupleStruct` of type `IndirectUninhabitedTupleStruct` is not handled - --> $DIR/indirect_match_same_crate.rs:42:11 + --> $DIR/indirect_match_same_crate.rs:43:11 | LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); | ------------------------------------------------------------------ @@ -41,7 +41,7 @@ LL | match x {} = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedVariants` of type `IndirectUninhabitedVariants` is not handled - --> $DIR/indirect_match_same_crate.rs:48:11 + --> $DIR/indirect_match_same_crate.rs:49:11 | LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); | ------------------------------------------------------------ diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs index 60289aa780378..d1e7c3b4d518a 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs @@ -3,6 +3,7 @@ #![deny(unreachable_patterns)] #![feature(exhaustive_patterns)] #![feature(never_type)] +#![feature(non_exhaustive)] #[non_exhaustive] pub enum UninhabitedEnum { diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs deleted file mode 100644 index 230ac75298e72..0000000000000 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs +++ /dev/null @@ -1,21 +0,0 @@ -// aux-build:uninhabited.rs -#![deny(unreachable_patterns)] -#![feature(never_type)] - -extern crate uninhabited; - -use uninhabited::PartiallyInhabitedVariants; - -// This test checks a redundant/useless pattern of a non-exhaustive enum/variant is still -// warned against. - -pub fn foo(x: PartiallyInhabitedVariants) { - match x { - PartiallyInhabitedVariants::Struct { .. } => {}, - PartiallyInhabitedVariants::Struct { .. } => {}, - //~^ ERROR unreachable pattern - _ => {}, - } -} - -fn main() { } diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr deleted file mode 100644 index f2b9983af8602..0000000000000 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: unreachable pattern - --> $DIR/issue-65157-repeated-match-arm.rs:15:9 - | -LL | PartiallyInhabitedVariants::Struct { .. } => {}, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: lint level defined here - --> $DIR/issue-65157-repeated-match-arm.rs:2:9 - | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs index ebbdfba15f3a3..6405dd3bd65b7 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs @@ -1,4 +1,5 @@ #![feature(never_type)] +#![feature(non_exhaustive)] #[non_exhaustive] pub enum UninhabitedEnum { diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr index c39df05a8f74e..410285a39a945 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: pattern `UninhabitedStruct` of type `UninhabitedStruct` is not handled - --> $DIR/match_same_crate.rs:30:11 + --> $DIR/match_same_crate.rs:31:11 | LL | pub struct UninhabitedStruct { | - ----------------- variant not covered @@ -15,7 +15,7 @@ LL | match x {} = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: pattern `UninhabitedTupleStruct` of type `UninhabitedTupleStruct` is not handled - --> $DIR/match_same_crate.rs:34:11 + --> $DIR/match_same_crate.rs:35:11 | LL | pub struct UninhabitedTupleStruct(!); | ------------------------------------- @@ -29,7 +29,7 @@ LL | match x {} = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: multiple patterns of type `UninhabitedVariants` are not handled - --> $DIR/match_same_crate.rs:38:11 + --> $DIR/match_same_crate.rs:39:11 | LL | / pub enum UninhabitedVariants { LL | | #[non_exhaustive] Tuple(!), diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs index de5530485f3e6..8973d21bff6fa 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs @@ -3,6 +3,7 @@ #![deny(unreachable_patterns)] #![feature(exhaustive_patterns)] #![feature(never_type)] +#![feature(non_exhaustive)] #[non_exhaustive] pub enum UninhabitedEnum { diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs index ffc496a975ecf..302a35cab5f90 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs @@ -1,6 +1,7 @@ #![deny(unreachable_patterns)] #![feature(exhaustive_patterns)] #![feature(never_type)] +#![feature(non_exhaustive)] #[non_exhaustive] pub enum UninhabitedEnum { diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr index e3de94be1282e..72f37d9a60ba8 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/patterns_same_crate.rs:52:9 + --> $DIR/patterns_same_crate.rs:53:9 | LL | Some(_x) => (), | ^^^^^^^^ @@ -11,25 +11,25 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/patterns_same_crate.rs:57:9 + --> $DIR/patterns_same_crate.rs:58:9 | LL | Some(_x) => (), | ^^^^^^^^ error: unreachable pattern - --> $DIR/patterns_same_crate.rs:61:15 + --> $DIR/patterns_same_crate.rs:62:15 | LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/patterns_same_crate.rs:65:15 + --> $DIR/patterns_same_crate.rs:66:15 | LL | while let Some(_x) = uninhabited_struct() { | ^^^^^^^^ error: unreachable pattern - --> $DIR/patterns_same_crate.rs:68:15 + --> $DIR/patterns_same_crate.rs:69:15 | LL | while let Some(_x) = uninhabited_tuple_struct() { | ^^^^^^^^ diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr index d9d6ea21b8bd4..ac0025ec75807 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr @@ -3,6 +3,8 @@ error[E0603]: tuple variant `Tuple` is private | LL | let variant_tuple = NonExhaustiveVariants::Tuple(640); | ^^^^^ + | + = note: a tuple variant constructor is private if any of its fields is private error[E0603]: unit variant `Unit` is private --> $DIR/variant.rs:14:47 @@ -21,12 +23,16 @@ error[E0603]: tuple variant `Tuple` is private | LL | NonExhaustiveVariants::Tuple(fe_tpl) => "", | ^^^^^ + | + = note: a tuple variant constructor is private if any of its fields is private error[E0603]: tuple variant `Tuple` is private --> $DIR/variant.rs:26:35 | LL | if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct { | ^^^^^ + | + = note: a tuple variant constructor is private if any of its fields is private error[E0639]: cannot create non-exhaustive variant using struct expression --> $DIR/variant.rs:8:26 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 5f2816ec62102..fe7df44590b8d 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 @@ -1,5 +1,7 @@ // run-pass +#![feature(non_exhaustive)] + pub enum NonExhaustiveVariants { #[non_exhaustive] Unit, #[non_exhaustive] Tuple(u32), diff --git a/src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs b/src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs deleted file mode 100644 index fa04f4b12d5fe..0000000000000 --- a/src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Check that we if we get ahold of an object unsafe trait -// object with auto traits and lifetimes, we can downcast it -// -// check-pass - -#![feature(object_safe_for_dispatch)] - -trait Trait: Sized {} - -fn downcast_auto(t: &(dyn Trait + Send)) -> &dyn Trait { - t -} - -fn downcast_lifetime<'a, 'b, 't>(t: &'a (dyn Trait + 't)) - -> &'b (dyn Trait + 't) -where - 'a: 'b, - 't: 'a + 'b, -{ - t -} - -fn main() {} diff --git a/src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs deleted file mode 100644 index 1dea401226569..0000000000000 --- a/src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Check that we can manually implement an object -// unsafe trait for its trait object -// -// run-pass - -#![feature(object_safe_for_dispatch)] - -trait Bad { - fn stat() -> char { - 'A' - } - fn virt(&self) -> char { - 'B' - } - fn indirect(&self) -> char { - Self::stat() - } -} - -trait Good { - fn good_virt(&self) -> char { - panic!() - } - fn good_indirect(&self) -> char { - panic!() - } -} - -impl<'a> Bad for dyn Bad + 'a { - fn stat() -> char { - 'C' - } - fn virt(&self) -> char { - 'D' - } -} - -struct Struct {} - -impl Bad for Struct {} - -impl Good for Struct {} - -fn main() { - let s = Struct {}; - - let mut res = String::new(); - - // Directly call static - res.push(Struct::stat()); // "A" - res.push(::stat()); // "AC" - - let good: &dyn Good = &s; - - // These look similar enough... - let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) }; - - // Call virtual - res.push(s.virt()); // "ACB" - res.push(bad.virt()); // "ACBD" - - // Indirectly call static - res.push(s.indirect()); // "ACBDA" - res.push(bad.indirect()); // "ACBDAC" - - if &res != "ACBDAC" { - panic!(); - } -} diff --git a/src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs b/src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs deleted file mode 100644 index df97d2c13278e..0000000000000 --- a/src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Check that we can statically dispatch methods for object -// unsafe trait objects, directly and indirectly -// -// check-pass - -#![feature(object_safe_for_dispatch)] - -trait Statics { - fn plain() {} - fn generic() {} -} - -trait Trait: Sized {} - -impl<'a> Statics for dyn Trait + 'a {} - -fn static_poly() { - T::plain(); - T::generic::(); -} - -fn inferred_poly(t: &T) { - static_poly::(); - T::plain(); - T::generic::(); -} - -fn call(t: &dyn Trait) { - static_poly::(); - inferred_poly(t); -} - -fn main() { - static_poly::(); - ::plain(); - ::generic::() -} diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs deleted file mode 100644 index d400db8575e0a..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete - -#[track_caller(1)] -fn f() {} -//~^^ ERROR malformed `track_caller` attribute input - -fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr deleted file mode 100644 index a53a8ee2bedc6..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: malformed `track_caller` attribute input - --> $DIR/error-odd-syntax.rs:3:1 - | -LL | #[track_caller(1)] - | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]` - -warning: the feature `track_caller` is incomplete and may cause the compiler to crash - --> $DIR/error-odd-syntax.rs:1:12 - | -LL | #![feature(track_caller)] - | ^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs deleted file mode 100644 index 2994f3c06212f..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete - -#[track_caller] -extern "C" fn f() {} -//~^^ ERROR rust ABI is required to use `#[track_caller]` - -fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr deleted file mode 100644 index a34acf3fc6142..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: the feature `track_caller` is incomplete and may cause the compiler to crash - --> $DIR/error-with-invalid-abi.rs:1:12 - | -LL | #![feature(track_caller)] - | ^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error[E0737]: rust ABI is required to use `#[track_caller]` - --> $DIR/error-with-invalid-abi.rs:3:1 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0737`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs deleted file mode 100644 index bbbcec30e8d51..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(naked_functions, track_caller)] //~ WARN the feature `track_caller` is incomplete - -#[track_caller] -#[naked] -fn f() {} -//~^^^ ERROR cannot use `#[track_caller]` with `#[naked]` - -fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr deleted file mode 100644 index 93e6f7a4cd32c..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: the feature `track_caller` is incomplete and may cause the compiler to crash - --> $DIR/error-with-naked.rs:1:29 - | -LL | #![feature(naked_functions, track_caller)] - | ^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error[E0736]: cannot use `#[track_caller]` with `#[naked]` - --> $DIR/error-with-naked.rs:3:1 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0736`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs deleted file mode 100644 index 1cd45c8cdbc91..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete - -trait Trait { - #[track_caller] - fn unwrap(&self); - //~^^ ERROR: `#[track_caller]` is not supported in trait declarations. -} - -impl Trait for u64 { - fn unwrap(&self) {} -} - -fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr deleted file mode 100644 index fb3732b597083..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: the feature `track_caller` is incomplete and may cause the compiler to crash - --> $DIR/error-with-trait-decl.rs:1:12 - | -LL | #![feature(track_caller)] - | ^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error[E0738]: `#[track_caller]` is not supported in trait declarations. - --> $DIR/error-with-trait-decl.rs:4:5 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0738`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs deleted file mode 100644 index 0f2020d6fb26b..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete - -trait Trait { - #[track_caller] - fn unwrap(&self) {} - //~^^ ERROR: `#[track_caller]` is not supported in trait declarations. -} - -fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr deleted file mode 100644 index c212a716c2024..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: the feature `track_caller` is incomplete and may cause the compiler to crash - --> $DIR/error-with-trait-default-impl.rs:1:12 - | -LL | #![feature(track_caller)] - | ^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error[E0738]: `#[track_caller]` is not supported in trait declarations. - --> $DIR/error-with-trait-default-impl.rs:4:5 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0738`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs deleted file mode 100644 index 1378ebaa03ffa..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete - -trait Trait { - fn unwrap(&self); -} - -impl Trait for u64 { - #[track_caller] - fn unwrap(&self) {} - //~^^ ERROR: `#[track_caller]` is not supported in traits yet. -} - -fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr deleted file mode 100644 index 2662fbff7a2c2..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: the feature `track_caller` is incomplete and may cause the compiler to crash - --> $DIR/error-with-trait-fn-impl.rs:1:12 - | -LL | #![feature(track_caller)] - | ^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error[E0738]: `#[track_caller]` is not supported in traits yet. - --> $DIR/error-with-trait-fn-impl.rs:8:5 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0738`. diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs deleted file mode 100644 index 01ebf13b521b2..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete - -#[track_caller] -struct S; -//~^^ ERROR attribute should be applied to function - -fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr deleted file mode 100644 index 3301da7ff47bf..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr +++ /dev/null @@ -1,18 +0,0 @@ -warning: the feature `track_caller` is incomplete and may cause the compiler to crash - --> $DIR/only-for-fns.rs:1:12 - | -LL | #![feature(track_caller)] - | ^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error[E0739]: attribute should be applied to function - --> $DIR/only-for-fns.rs:3:1 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ -LL | struct S; - | --------- not a function - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-2091-track-caller/pass.rs b/src/test/ui/rfc-2091-track-caller/pass.rs deleted file mode 100644 index f2c3f0dc59e01..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/pass.rs +++ /dev/null @@ -1,9 +0,0 @@ -// run-pass -#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete - -#[track_caller] -fn f() {} - -fn main() { - f(); -} diff --git a/src/test/ui/rfc-2091-track-caller/pass.stderr b/src/test/ui/rfc-2091-track-caller/pass.stderr deleted file mode 100644 index b1fd23a6a9ddb..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/pass.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: the feature `track_caller` is incomplete and may cause the compiler to crash - --> $DIR/pass.rs:2:12 - | -LL | #![feature(track_caller)] - | ^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs index ea8a3c177e9d7..a16fb7670a603 100644 --- a/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs +++ b/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs @@ -1,12 +1,13 @@ #![feature(rustc_attrs)] #![feature(untagged_unions)] +#![allow(unions_with_drop_fields)] #[rustc_outlives] -union Foo<'b, U: Copy> { //~ ERROR rustc_outlives +union Foo<'b, U> { //~ ERROR rustc_outlives bar: Bar<'b, U> } -union Bar<'a, T: Copy> where T: 'a { +union Bar<'a, T> where T: 'a { x: &'a (), y: T, } diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr index 8aa246e8bfeb3..adf62651cacb1 100644 --- a/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr @@ -1,7 +1,7 @@ error: rustc_outlives - --> $DIR/explicit-union.rs:5:1 + --> $DIR/explicit-union.rs:6:1 | -LL | / union Foo<'b, U: Copy> { +LL | / union Foo<'b, U> { LL | | bar: Bar<'b, U> LL | | } | |_^ diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-union.rs b/src/test/ui/rfc-2093-infer-outlives/nested-union.rs index 0da3cc2ba1b04..0ff667fbeba64 100644 --- a/src/test/ui/rfc-2093-infer-outlives/nested-union.rs +++ b/src/test/ui/rfc-2093-infer-outlives/nested-union.rs @@ -1,13 +1,14 @@ #![feature(rustc_attrs)] #![feature(untagged_unions)] +#![allow(unions_with_drop_fields)] #[rustc_outlives] -union Foo<'a, T: Copy> { //~ ERROR rustc_outlives +union Foo<'a, T> { //~ ERROR rustc_outlives field1: Bar<'a, T> } // Type U needs to outlive lifetime 'b -union Bar<'b, U: Copy> { +union Bar<'b, U> { field2: &'b U } diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr b/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr index a42285a56d089..fc4b1a223294d 100644 --- a/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr @@ -1,7 +1,7 @@ error: rustc_outlives - --> $DIR/nested-union.rs:5:1 + --> $DIR/nested-union.rs:6:1 | -LL | / union Foo<'a, T: Copy> { +LL | / union Foo<'a, T> { LL | | field1: Bar<'a, T> LL | | } | |_^ diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr index 6efc1176d05b8..be8b5c6446cad 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a rev_variant_struct_region::Foo<'b>`, reference has a LL | type Out = &'a Foo<'b>; | ^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10 +note: the pointer is valid for the lifetime 'a as defined on the impl at 16:10 --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:10 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 16:14 +note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 16:14 --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:14 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr index 06e5f24dec970..9a3ba2d65cad7 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a variant_struct_region::Foo<'b>`, reference has a long LL | type Out = &'a Foo<'b>; | ^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10 +note: the pointer is valid for the lifetime 'a as defined on the impl at 16:10 --> $DIR/regions-outlives-nominal-type-region.rs:16:10 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 16:14 +note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 16:14 --> $DIR/regions-outlives-nominal-type-region.rs:16:14 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr index d02f7b7962184..5389beea3a70c 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a variant_struct_type::Foo<&'b i32>`, reference has a l LL | type Out = &'a Foo<&'b i32>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10 +note: the pointer is valid for the lifetime 'a as defined on the impl at 16:10 --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:10 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 16:14 +note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 16:14 --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:14 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr index 40c70f53245cf..2f3ef48a05441 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a variant_struct_type::Foo<&'b i32>`, reference has a l LL | type Out = &'a Foo<&'b i32>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10 +note: the pointer is valid for the lifetime 'a as defined on the impl at 16:10 --> $DIR/regions-outlives-nominal-type-type.rs:16:10 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 16:14 +note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 16:14 --> $DIR/regions-outlives-nominal-type-type.rs:16:14 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr index 825c1015c51d7..5a11c5fb95fef 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr @@ -32,12 +32,12 @@ error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data LL | type Out = &'a &'b T; | ^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the impl at 24:6 +note: the pointer is valid for the lifetime 'a as defined on the impl at 24:6 --> $DIR/regions-struct-not-wf.rs:24:6 | LL | impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 24:10 +note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 24:10 --> $DIR/regions-struct-not-wf.rs:24:10 | LL | impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 { diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index ad4686c1915d6..4edc00efc7e72 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -517,10 +517,7 @@ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:32:8 | LL | if &let 0 = 0 {} - | ^^^^^^^^^^ - | | - | expected bool, found &bool - | help: consider removing the borrow: `let 0 = 0` + | ^^^^^^^^^^ expected bool, found &bool | = note: expected type `bool` found type `&bool` @@ -705,10 +702,7 @@ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:96:11 | LL | while &let 0 = 0 {} - | ^^^^^^^^^^ - | | - | expected bool, found &bool - | help: consider removing the borrow: `let 0 = 0` + | ^^^^^^^^^^ expected bool, found &bool | = note: expected type `bool` found type `&bool` 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 deleted file mode 100644 index eeb2191bab462..0000000000000 --- a/src/test/ui/rfc-2565-param-attrs/attr-without-param.rs +++ /dev/null @@ -1,16 +0,0 @@ -#[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 deleted file mode 100644 index 26dff4d4b30bf..0000000000000 --- a/src/test/ui/rfc-2565-param-attrs/attr-without-param.stderr +++ /dev/null @@ -1,20 +0,0 @@ -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/param-attrs.rs b/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs index c537c1034b5a6..71815e3c08974 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,6 +11,7 @@ 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() } @@ -27,18 +28,7 @@ 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 deleted file mode 100644 index 670303906d24c..0000000000000 --- a/src/test/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs +++ /dev/null @@ -1,21 +0,0 @@ -// 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.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr index e4248f3b974b9..9860e9805b2ed 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 @@ -5,10 +5,6 @@ LL | trait Trait2015 { fn foo(#[allow(C)] i32); } | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this is a `self` type, give it a parameter name - | -LL | trait Trait2015 { fn foo(#[allow(C)] self: i32); } - | ^^^^^^^^^ help: if this was a parameter name, give it a type | LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); } 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 bf09171c9a12a..c4684a3fa82b0 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 @@ -64,21 +64,6 @@ impl SelfStruct { #[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] - //~^ 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 - ) {} } struct RefStruct {} @@ -119,23 +104,7 @@ trait RefTrait { #[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] - //~^ 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 - ) {} } - impl RefTrait for RefStruct { fn foo( /// Foo 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 4d0349e8765f0..0fc6ca2f7f37a 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 @@ -23,37 +23,25 @@ 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 + --> $DIR/param-attrs-builtin-attrs.rs:77:9 | LL | #[test] a: i32, | ^^^^^^^ error: expected an inert attribute, found an attribute macro - --> $DIR/param-attrs-builtin-attrs.rs:126:9 + --> $DIR/param-attrs-builtin-attrs.rs:96:9 | LL | #[test] a: i32, | ^^^^^^^ error: expected an inert attribute, found an attribute macro - --> $DIR/param-attrs-builtin-attrs.rs:146:9 + --> $DIR/param-attrs-builtin-attrs.rs:115:9 | LL | #[test] a: i32, | ^^^^^^^ error: expected an inert attribute, found an attribute macro - --> $DIR/param-attrs-builtin-attrs.rs:163:9 + --> $DIR/param-attrs-builtin-attrs.rs:132:9 | LL | #[test] a: u32, | ^^^^^^^ @@ -185,202 +173,142 @@ LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:69:9 + --> $DIR/param-attrs-builtin-attrs.rs:72:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $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:75:9 | -LL | #[must_use] - | ^^^^^^^^^^^ - -error: documentation comments cannot be applied to function parameters - --> $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:79:9 - | -LL | #[no_mangle] b: i32, - | ^^^^^^^^^^^^ - -error: documentation comments cannot be applied to function parameters - --> $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: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:94:9 + --> $DIR/param-attrs-builtin-attrs.rs:79: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:96:9 + --> $DIR/param-attrs-builtin-attrs.rs:81:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:98:9 + --> $DIR/param-attrs-builtin-attrs.rs:83: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:100:9 + --> $DIR/param-attrs-builtin-attrs.rs:85:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:106:9 + --> $DIR/param-attrs-builtin-attrs.rs:91:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:109:9 + --> $DIR/param-attrs-builtin-attrs.rs:94:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $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:115:9 - | -LL | #[must_use] - | ^^^^^^^^^^^ - -error: documentation comments cannot be applied to function parameters - --> $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:119:9 - | -LL | #[no_mangle] b: i32, - | ^^^^^^^^^^^^ - -error: documentation comments cannot be applied to function parameters - --> $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:128:9 + --> $DIR/param-attrs-builtin-attrs.rs:98: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:130:9 + --> $DIR/param-attrs-builtin-attrs.rs:100:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:132:9 + --> $DIR/param-attrs-builtin-attrs.rs:102: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:134:9 + --> $DIR/param-attrs-builtin-attrs.rs:104:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:141:9 + --> $DIR/param-attrs-builtin-attrs.rs:110:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:144:9 + --> $DIR/param-attrs-builtin-attrs.rs:113:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:148:9 + --> $DIR/param-attrs-builtin-attrs.rs:117: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:150:9 + --> $DIR/param-attrs-builtin-attrs.rs:119:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:152:9 + --> $DIR/param-attrs-builtin-attrs.rs:121: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:154:9 + --> $DIR/param-attrs-builtin-attrs.rs:123:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:161:9 + --> $DIR/param-attrs-builtin-attrs.rs:130:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:165:9 + --> $DIR/param-attrs-builtin-attrs.rs:134: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:167:9 + --> $DIR/param-attrs-builtin-attrs.rs:136:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:169:9 + --> $DIR/param-attrs-builtin-attrs.rs:138: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:171:9 + --> $DIR/param-attrs-builtin-attrs.rs:140:9 | LL | #[no_mangle] b: i32 | ^^^^^^^^^^^^ -error: aborting due to 64 previous errors +error: aborting due to 52 previous errors 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 a4d9d32b514ac..d44ff14e99247 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 @@ -51,14 +51,6 @@ 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( @@ -70,14 +62,6 @@ 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( @@ -89,14 +73,6 @@ 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 8d9571d09a856..3232e2a0411a2 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,43 +23,31 @@ LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ help: consider prefixing with an underscore: `_c` error: unused variable: `a` - --> $DIR/param-attrs-cfg.rs:107:27 + --> $DIR/param-attrs-cfg.rs:83:27 | LL | #[cfg(something)] a: i32, | ^ help: consider prefixing with an underscore: `_a` error: unused variable: `b` - --> $DIR/param-attrs-cfg.rs:113:27 + --> $DIR/param-attrs-cfg.rs:89:27 | LL | #[cfg(something)] b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `c` - --> $DIR/param-attrs-cfg.rs:115:44 + --> $DIR/param-attrs-cfg.rs:91: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:67:27 + --> $DIR/param-attrs-cfg.rs:59:27 | LL | #[cfg(something)] b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `c` - --> $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 + --> $DIR/param-attrs-cfg.rs:61:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ help: consider prefixing with an underscore: `_c` @@ -83,40 +71,16 @@ LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ help: consider prefixing with an underscore: `_c` error: unused variable: `b` - --> $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 + --> $DIR/param-attrs-cfg.rs:70:27 | LL | #[cfg(something)] b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `c` - --> $DIR/param-attrs-cfg.rs:96:44 + --> $DIR/param-attrs-cfg.rs:72:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ help: consider prefixing with an underscore: `_c` -error: aborting due to 19 previous errors +error: aborting due to 13 previous errors 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 1183ac65b9a7f..fb86020d992e9 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 @@ -36,9 +36,6 @@ 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 { @@ -53,9 +50,6 @@ 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 index be9085d5878cb..e2680446f851a 100644 --- 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 @@ -38,9 +38,6 @@ impl W { 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 { @@ -57,9 +54,6 @@ trait A { //~^ 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 index 1cc3c3d82281b..4654dc1b496f2 100644 --- 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 @@ -95,82 +95,58 @@ 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 + --> $DIR/proc-macro-cannot-be-used.rs:44: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 + --> $DIR/proc-macro-cannot-be-used.rs:44: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 + --> $DIR/proc-macro-cannot-be-used.rs:47: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 + --> $DIR/proc-macro-cannot-be-used.rs:47: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 + --> $DIR/proc-macro-cannot-be-used.rs:50: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 + --> $DIR/proc-macro-cannot-be-used.rs:50: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 + --> $DIR/proc-macro-cannot-be-used.rs:53: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 + --> $DIR/proc-macro-cannot-be-used.rs:53: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 + --> $DIR/proc-macro-cannot-be-used.rs:53: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 +error: aborting due to 25 previous errors diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs deleted file mode 100644 index 14345bad6e5b9..0000000000000 --- a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[link(name="foo")] -extern { - #[link_ordinal(42)] - //~^ ERROR: the `#[link_ordinal]` attribute is an experimental feature - fn foo(); -} - -fn main() {} diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr deleted file mode 100644 index 0869d7ad48a8c..0000000000000 --- a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: the `#[link_ordinal]` attribute is an experimental feature - --> $DIR/feature-gate-raw-dylib-2.rs:3:5 - | -LL | #[link_ordinal(42)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/58713 - = help: add `#![feature(raw_dylib)]` 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/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs deleted file mode 100644 index f0f83e0426dd6..0000000000000 --- a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[link(name="foo", kind="raw-dylib")] -//~^ ERROR: kind="raw-dylib" is unstable -extern {} - -fn main() {} diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr deleted file mode 100644 index 0ca9de28be1ac..0000000000000 --- a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: kind="raw-dylib" is unstable - --> $DIR/feature-gate-raw-dylib.rs:1:1 - | -LL | #[link(name="foo", kind="raw-dylib")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/58713 - = help: add `#![feature(raw_dylib)]` 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/rfc-2627-raw-dylib/link-ordinal-and-name.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs deleted file mode 100644 index 5769366fb45a4..0000000000000 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(raw_dylib)] -//~^ WARN the feature `raw_dylib` is incomplete and may cause the compiler to crash - -#[link(name="foo")] -extern { - #[link_name="foo"] - #[link_ordinal(42)] - //~^ ERROR cannot use `#[link_name]` with `#[link_ordinal]` - fn foo(); -} - -fn main() {} diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr deleted file mode 100644 index 303a1c02eb85f..0000000000000 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr +++ /dev/null @@ -1,16 +0,0 @@ -warning: the feature `raw_dylib` is incomplete and may cause the compiler to crash - --> $DIR/link-ordinal-and-name.rs:1:12 - | -LL | #![feature(raw_dylib)] - | ^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error: cannot use `#[link_name]` with `#[link_ordinal]` - --> $DIR/link-ordinal-and-name.rs:7:5 - | -LL | #[link_ordinal(42)] - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs deleted file mode 100644 index 82fb1151c23df..0000000000000 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(raw_dylib)] -//~^ WARN the feature `raw_dylib` is incomplete and may cause the compiler to crash - -#[link(name="foo")] -extern { - #[link_ordinal("JustMonika")] - //~^ ERROR illegal ordinal format in `link_ordinal` - fn foo(); -} - -fn main() {} diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr deleted file mode 100644 index 14556a7262b1c..0000000000000 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr +++ /dev/null @@ -1,18 +0,0 @@ -warning: the feature `raw_dylib` is incomplete and may cause the compiler to crash - --> $DIR/link-ordinal-invalid-format.rs:1:12 - | -LL | #![feature(raw_dylib)] - | ^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error: illegal ordinal format in `link_ordinal` - --> $DIR/link-ordinal-invalid-format.rs:6:5 - | -LL | #[link_ordinal("JustMonika")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: an unsuffixed integer value, e.g., `1`, is expected - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs deleted file mode 100644 index 69596ad04fff3..0000000000000 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(raw_dylib)] -//~^ WARN the feature `raw_dylib` is incomplete and may cause the compiler to crash - -#[link(name="foo")] -extern { - #[link_ordinal(18446744073709551616)] - //~^ ERROR ordinal value in `link_ordinal` is too large: `18446744073709551616` - fn foo(); -} - -fn main() {} diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr deleted file mode 100644 index b3b22f9776df7..0000000000000 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr +++ /dev/null @@ -1,18 +0,0 @@ -warning: the feature `raw_dylib` is incomplete and may cause the compiler to crash - --> $DIR/link-ordinal-too-large.rs:1:12 - | -LL | #![feature(raw_dylib)] - | ^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -error: ordinal value in `link_ordinal` is too large: `18446744073709551616` - --> $DIR/link-ordinal-too-large.rs:6:5 - | -LL | #[link_ordinal(18446744073709551616)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the value may not exceed `std::usize::MAX` - -error: aborting due to previous error - diff --git a/src/test/ui/rfcs/rfc-2005-default-binding-mode/range.rs b/src/test/ui/rfcs/rfc-2005-default-binding-mode/range.rs index f8abd1b96d80e..580e67513b396 100644 --- a/src/test/ui/rfcs/rfc-2005-default-binding-mode/range.rs +++ b/src/test/ui/rfcs/rfc-2005-default-binding-mode/range.rs @@ -3,7 +3,7 @@ pub fn main() { let i = 5; match &&&&i { 1 ..= 3 => panic!(), - 4 ..= 8 => {}, + 3 ..= 8 => {}, _ => panic!(), } } diff --git a/src/test/ui/rfcs/rfc1857-drop-order.rs b/src/test/ui/rfcs/rfc1857-drop-order.rs index b10b6ec11b53a..7923aa7c0e22f 100644 --- a/src/test/ui/rfcs/rfc1857-drop-order.rs +++ b/src/test/ui/rfcs/rfc1857-drop-order.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![allow(dead_code, unreachable_code)] diff --git a/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr b/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr index 973c486970e65..030fa56dcff2f 100644 --- a/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr +++ b/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr @@ -13,7 +13,7 @@ LL | use std::collections::hash_map::Drain; | LL | use std::collections::hash_set::Drain; | - and 3 other candidates +and 3 other candidates error: aborting due to previous error diff --git a/src/test/ui/rust-2018/trait-import-suggestions.stderr b/src/test/ui/rust-2018/trait-import-suggestions.stderr index 4b1898345a32e..19f758fd8da77 100644 --- a/src/test/ui/rust-2018/trait-import-suggestions.stderr +++ b/src/test/ui/rust-2018/trait-import-suggestions.stderr @@ -5,7 +5,7 @@ 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: + = note: the following trait is implemented but not in scope, perhaps add a `use` for it: `use crate::foo::foobar::Foobar;` error[E0599]: no method named `bar` found for type `u32` in the current scope @@ -15,7 +15,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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use crate::foo::Bar; | @@ -33,7 +33,7 @@ LL | let y = u32::from_str("33"); | ^^^^^^^^ function or associated item 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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use std::str::FromStr; | diff --git a/src/test/ui/save-analysis/issue-64659.rs b/src/test/ui/save-analysis/issue-64659.rs deleted file mode 100644 index a3d88a203778f..0000000000000 --- a/src/test/ui/save-analysis/issue-64659.rs +++ /dev/null @@ -1,10 +0,0 @@ -// 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 deleted file mode 100644 index 9e58b8da5d271..0000000000000 --- a/src/test/ui/save-analysis/issue-65411.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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/self/arbitrary-self-types-not-object-safe.curr.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr deleted file mode 100644 index cdffc1d86edfb..0000000000000 --- a/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:34: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 - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:34: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: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::rc::Rc` - = note: required by cast to type `std::rc::Rc` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr deleted file mode 100644 index 725632a12126e..0000000000000 --- a/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:34: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: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::rc::Rc` - = note: required by cast to type `std::rc::Rc` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.rs b/src/test/ui/self/arbitrary-self-types-not-object-safe.rs index 2eeabad28db02..7443d888c9ec8 100644 --- a/src/test/ui/self/arbitrary-self-types-not-object-safe.rs +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.rs @@ -1,6 +1,3 @@ -// revisions: curr object_safe_for_dispatch - -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] #![feature(arbitrary_self_types)] use std::rc::Rc; @@ -32,9 +29,8 @@ impl Bar for usize { fn make_foo() { let x = Rc::new(5usize) as Rc; - //[curr]~^ ERROR E0038 - //[curr]~| ERROR E0038 - //[object_safe_for_dispatch]~^^^ ERROR E0038 + //~^ ERROR E0038 + //~| ERROR E0038 } fn make_bar() { 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 index bce1900ca602c..2fb152475a1ef 100644 --- 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 @@ -6,12 +6,12 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self } | | | ...but this borrow... | -note: ...can't outlive the lifetime `'_` as defined on the method body at 8:26 +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 +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 } | ^^^^^^^^^^^^^^^ 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 index 7eec31d36e39e..e53d91c360489 100644 --- 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 @@ -7,19 +7,19 @@ 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:52 + --> $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 `'_` + | - ^^^^^ 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:75 + --> $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 `'_` + | - ^^^^^^^^^^^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | | | lifetime `'_` defined here | lifetime `'_` defined here @@ -33,11 +33,12 @@ 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:64 + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:62 | LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } - | -- - lifetime `'_` defined here ^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'a` - | | + | -- - ^^^^^^^ 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 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 index e3c261576e61e..57ad026bdcf97 100644 --- 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 @@ -1,25 +1,28 @@ error[E0623]: lifetime mismatch - --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52 + --> $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 - | | + | ---- ^^^^ + | | | + | | ...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:82 + --> $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 - | | + | ----- ^^^^^^^^^^^^^^^^^ + | | | + | | ...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:64 + --> $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 - | | + | ----- ^^^ + | | | + | | ...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/lt-ref-self-async.nll.stderr b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr index b4f8ff6001d60..998178dde1df1 100644 --- a/src/test/ui/self/elision/lt-ref-self-async.nll.stderr +++ b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr @@ -7,15 +7,16 @@ 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:14:9 - | -LL | async fn ref_self(&self, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -26,15 +27,16 @@ 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:20:9 - | -LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -45,15 +47,16 @@ 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:24:9 - | -LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -64,15 +67,16 @@ 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:28:9 - | -LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -83,15 +87,16 @@ 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:32:9 - | -LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -102,15 +107,16 @@ 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:36:9 - | -LL | async fn box_pin_Self(self: Box>, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 diff --git a/src/test/ui/self/elision/lt-ref-self-async.rs b/src/test/ui/self/elision/lt-ref-self-async.rs index 5aba7cfcf296e..e3ca0c2e2dd9d 100644 --- a/src/test/ui/self/elision/lt-ref-self-async.rs +++ b/src/test/ui/self/elision/lt-ref-self-async.rs @@ -11,29 +11,29 @@ impl<'a> Struct<'a> { // Test using `&self` sugar: async fn ref_self(&self, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } // Test using `&Self` explicitly: async fn ref_Self(self: &Self, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_pin_Self(self: Box>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } } diff --git a/src/test/ui/self/elision/lt-ref-self-async.stderr b/src/test/ui/self/elision/lt-ref-self-async.stderr index 6b668d9f1f655..2bc64bdf1f7a2 100644 --- a/src/test/ui/self/elision/lt-ref-self-async.stderr +++ b/src/test/ui/self/elision/lt-ref-self-async.stderr @@ -1,62 +1,56 @@ error[E0623]: lifetime mismatch - --> $DIR/lt-ref-self-async.rs:14:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/lt-ref-self-async.rs:20:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/lt-ref-self-async.rs:24:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/lt-ref-self-async.rs:28:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/lt-ref-self-async.rs:32:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/lt-ref-self-async.rs:36:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error: aborting due to 6 previous errors 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 index b6f2b63f093b1..97bc80509dfea 100644 --- a/src/test/ui/self/elision/ref-mut-self-async.nll.stderr +++ b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr @@ -7,15 +7,16 @@ 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:14:9 - | -LL | async fn ref_self(&mut self, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -26,15 +27,16 @@ 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:20:9 - | -LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -45,15 +47,16 @@ 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:24:9 - | -LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -64,15 +67,16 @@ 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:28:9 - | -LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -83,15 +87,16 @@ 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:32:9 - | -LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -102,15 +107,16 @@ 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:36:9 - | -LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 diff --git a/src/test/ui/self/elision/ref-mut-self-async.rs b/src/test/ui/self/elision/ref-mut-self-async.rs index b8eb416d90432..2ca14800a7556 100644 --- a/src/test/ui/self/elision/ref-mut-self-async.rs +++ b/src/test/ui/self/elision/ref-mut-self-async.rs @@ -10,30 +10,30 @@ struct Struct { } impl Struct { // Test using `&mut self` sugar: - async fn ref_self(&mut self, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + 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 + f //~^ ERROR lifetime mismatch } async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } } diff --git a/src/test/ui/self/elision/ref-mut-self-async.stderr b/src/test/ui/self/elision/ref-mut-self-async.stderr index 29fbec9fa7ae0..39a1b30ca5329 100644 --- a/src/test/ui/self/elision/ref-mut-self-async.stderr +++ b/src/test/ui/self/elision/ref-mut-self-async.stderr @@ -1,62 +1,56 @@ error[E0623]: lifetime mismatch - --> $DIR/ref-mut-self-async.rs:14:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-mut-self-async.rs:20:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-mut-self-async.rs:24:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-mut-self-async.rs:28:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-mut-self-async.rs:32:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-mut-self-async.rs:36:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here 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 index fa78543bd87ab..2905a022e5d6e 100644 --- a/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr +++ b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr @@ -7,15 +7,16 @@ 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:14:9 + --> $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 - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` +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 @@ -26,15 +27,16 @@ 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:18:9 + --> $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 - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` +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 @@ -45,15 +47,16 @@ 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:22:9 + --> $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 - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` +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 @@ -64,15 +67,16 @@ LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u = note: hidden type `impl std::future::Future` captures lifetime '_#15r error: lifetime may not live long enough - --> $DIR/ref-mut-struct-async.rs:26:9 + --> $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 - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` +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 @@ -83,15 +87,16 @@ LL | async fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u = note: hidden type `impl std::future::Future` captures lifetime '_#15r error: lifetime may not live long enough - --> $DIR/ref-mut-struct-async.rs:30:9 + --> $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 - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` +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 diff --git a/src/test/ui/self/elision/ref-mut-struct-async.rs b/src/test/ui/self/elision/ref-mut-struct-async.rs index 1822a9a468b0e..a671116de2543 100644 --- a/src/test/ui/self/elision/ref-mut-struct-async.rs +++ b/src/test/ui/self/elision/ref-mut-struct-async.rs @@ -11,23 +11,23 @@ impl Struct { // Test using `&mut Struct` explicitly: async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } } diff --git a/src/test/ui/self/elision/ref-mut-struct-async.stderr b/src/test/ui/self/elision/ref-mut-struct-async.stderr index 46591bfc9580f..fe4a636ada668 100644 --- a/src/test/ui/self/elision/ref-mut-struct-async.stderr +++ b/src/test/ui/self/elision/ref-mut-struct-async.stderr @@ -1,52 +1,47 @@ error[E0623]: lifetime mismatch - --> $DIR/ref-mut-struct-async.rs:14:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-mut-struct-async.rs:18:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-mut-struct-async.rs:22:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-mut-struct-async.rs:26:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-mut-struct-async.rs:30:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here 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 index 88fd2101bc619..0eee56654f7d1 100644 --- a/src/test/ui/self/elision/ref-self-async.nll.stderr +++ b/src/test/ui/self/elision/ref-self-async.nll.stderr @@ -7,15 +7,16 @@ 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:23:9 - | -LL | async fn ref_self(&self, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -26,15 +27,16 @@ 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:29:9 - | -LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -45,15 +47,16 @@ 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:33:9 - | -LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -64,15 +67,16 @@ 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:37:9 - | -LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -83,15 +87,16 @@ 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:41:9 - | -LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -102,15 +107,16 @@ 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:45:9 - | -LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 @@ -121,15 +127,16 @@ 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:49:9 - | -LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { - | - - | | - | lifetime `'_` defined here - | lifetime `'_` defined here -LL | f - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + --> $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 diff --git a/src/test/ui/self/elision/ref-self-async.rs b/src/test/ui/self/elision/ref-self-async.rs index 9425fbfca8f08..06f3b127b216a 100644 --- a/src/test/ui/self/elision/ref-self-async.rs +++ b/src/test/ui/self/elision/ref-self-async.rs @@ -19,34 +19,34 @@ impl Deref for Wrap { impl Struct { // Test using `&self` sugar: - async fn ref_self(&self, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + 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 + f //~^ ERROR lifetime mismatch } async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } } diff --git a/src/test/ui/self/elision/ref-self-async.stderr b/src/test/ui/self/elision/ref-self-async.stderr index c255d18936376..2f9e2a01e347c 100644 --- a/src/test/ui/self/elision/ref-self-async.stderr +++ b/src/test/ui/self/elision/ref-self-async.stderr @@ -1,72 +1,65 @@ error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:23:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:29:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:33:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:37:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:41:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:45:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:49:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here 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 index 93fec69ec343a..8508e42264b4a 100644 --- a/src/test/ui/self/elision/ref-struct-async.nll.stderr +++ b/src/test/ui/self/elision/ref-struct-async.nll.stderr @@ -7,15 +7,16 @@ 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:14:9 + --> $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 - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` +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 @@ -26,15 +27,16 @@ 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:18:9 + --> $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 - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` +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 @@ -45,15 +47,16 @@ 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:22:9 + --> $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 - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` +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 @@ -64,15 +67,16 @@ 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:26:9 + --> $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 - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` +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 @@ -83,15 +87,16 @@ 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:30:9 + --> $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 - | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` +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 diff --git a/src/test/ui/self/elision/ref-struct-async.rs b/src/test/ui/self/elision/ref-struct-async.rs index 64c84c4cd2eb9..94eaeedc734ff 100644 --- a/src/test/ui/self/elision/ref-struct-async.rs +++ b/src/test/ui/self/elision/ref-struct-async.rs @@ -11,23 +11,23 @@ impl Struct { // Test using `&Struct` explicitly: async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } async fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { - f //~ ERROR lifetime mismatch + f //~^ ERROR lifetime mismatch } } diff --git a/src/test/ui/self/elision/ref-struct-async.stderr b/src/test/ui/self/elision/ref-struct-async.stderr index c70facc931ec1..222e27ebf0d97 100644 --- a/src/test/ui/self/elision/ref-struct-async.stderr +++ b/src/test/ui/self/elision/ref-struct-async.stderr @@ -1,52 +1,47 @@ error[E0623]: lifetime mismatch - --> $DIR/ref-struct-async.rs:14:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-struct-async.rs:18:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-struct-async.rs:22:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-struct-async.rs:26:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-struct-async.rs:30:9 + --> $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... -LL | f - | ^ ...but data from `f` is returned here error: aborting due to 5 previous errors diff --git a/src/test/ui/self/self-in-typedefs.rs b/src/test/ui/self/self-in-typedefs.rs index 3b1eb9e1dfa16..73f23a9cc17cf 100644 --- a/src/test/ui/self/self-in-typedefs.rs +++ b/src/test/ui/self/self-in-typedefs.rs @@ -3,8 +3,7 @@ #![feature(untagged_unions)] #![allow(dead_code)] - -use std::mem::ManuallyDrop; +#![allow(unions_with_drop_fields)] enum A<'a, T: 'a> where @@ -25,14 +24,6 @@ where union C<'a, T: 'a> where Self: Send, T: PartialEq -{ - foo: &'a Self, - bar: ManuallyDrop, -} - -union D<'a, T: 'a> -where - Self: Send, T: PartialEq + Copy { foo: &'a Self, bar: T, diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr index 0af24dcedfbea..6534d8c36e343 100644 --- a/src/test/ui/self/self_type_keyword.stderr +++ b/src/test/ui/self/self_type_keyword.stderr @@ -76,7 +76,7 @@ error[E0392]: parameter `'Self` is never used LL | struct Bar<'Self>; | ^^^^^ unused parameter | - = help: consider removing `'Self`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `'Self` or using a marker such as `std::marker::PhantomData` error: aborting due to 12 previous errors diff --git a/src/test/ui/sepcomp/sepcomp-lib-lto.rs b/src/test/ui/sepcomp/sepcomp-lib-lto.rs index 51a572899f819..164ae79c254fa 100644 --- a/src/test/ui/sepcomp/sepcomp-lib-lto.rs +++ b/src/test/ui/sepcomp/sepcomp-lib-lto.rs @@ -4,7 +4,6 @@ // aux-build:sepcomp_lib.rs // compile-flags: -C lto -g -// ignore-asmjs wasm2js does not support source maps yet // no-prefer-dynamic extern crate sepcomp_lib; diff --git a/src/test/ui/shadowed/shadowed-trait-methods.stderr b/src/test/ui/shadowed/shadowed-trait-methods.stderr index 3597cc53420aa..190159ec7b88d 100644 --- a/src/test/ui/shadowed/shadowed-trait-methods.stderr +++ b/src/test/ui/shadowed/shadowed-trait-methods.stderr @@ -5,7 +5,7 @@ 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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use foo::T; | diff --git a/src/test/ui/signal-alternate-stack-cleanup.rs b/src/test/ui/signal-alternate-stack-cleanup.rs index 8fef66eac8de2..787ff51799a8a 100644 --- a/src/test/ui/signal-alternate-stack-cleanup.rs +++ b/src/test/ui/signal-alternate-stack-cleanup.rs @@ -7,7 +7,6 @@ // ignore-wasm32-bare no libc // ignore-windows // ignore-sgx no libc -// ignore-vxworks no SIGWINCH in user space #![feature(rustc_private)] extern crate libc; diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr index d05e89e257f45..7e164ba9681c6 100644 --- a/src/test/ui/span/E0493.stderr +++ b/src/test/ui/span/E0493.stderr @@ -6,4 +6,3 @@ LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; error: aborting due to previous error -For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr index 0d15a2a753ed0..996d80a07e058 100644 --- a/src/test/ui/span/coerce-suggestions.stderr +++ b/src/test/ui/span/coerce-suggestions.stderr @@ -44,7 +44,7 @@ LL | f = box f; | ^^^^^ | | | cyclic type of infinite size - | help: try using a conversion method: `(box f).to_string()` + | help: try using a conversion method: `box f.to_string()` error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:21:9 diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 8d4a66f142d2c..cc0eccd37a26f 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -3,12 +3,6 @@ error: expected one of `:`, `@`, or `|`, found `<` | LL | fn foo(Option, String) {} | ^ expected one of `:`, `@`, or `|` here - | - = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this is a type, explicitly ignore the parameter name - | -LL | fn foo(_: Option, String) {} - | ^^^^^^^^^ error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/issue-34264.rs:1:27 diff --git a/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs b/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs index 1e5555355c3b3..5cf975b5752f0 100644 --- a/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs +++ b/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs @@ -22,9 +22,7 @@ pub trait Bar { fn bar(&self) -> i32 { 0 } } -impl Bar for T { - default fn bar(&self) -> i32 { 0 } -} +impl Bar for T {} // use the provided method impl Bar for i32 { fn bar(&self) -> i32 { 1 } diff --git a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr index 5275b7b1ddfa5..45951561e7264 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr @@ -2,9 +2,9 @@ error[E0277]: the trait bound `U: std::cmp::Eq` is not satisfied --> $DIR/specialization-wfcheck.rs:7:17 | LL | default impl Foo<'static, U> for () {} - | - ^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `U` - | | - | help: consider restricting this bound: `U: std::cmp::Eq` + | ^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `U` + | + = help: consider adding a `where U: std::cmp::Eq` bound error: aborting due to previous error diff --git a/src/test/ui/specialization/issue-36804.rs b/src/test/ui/specialization/issue-36804.rs index 9546a5dd5f516..36cb939bc48fb 100644 --- a/src/test/ui/specialization/issue-36804.rs +++ b/src/test/ui/specialization/issue-36804.rs @@ -13,10 +13,6 @@ where fn next(&mut self) -> Option { unimplemented!() } - - default fn count(self) -> usize where Self: Sized { - self.fold(0, |cnt, _| cnt + 1) - } } impl<'a, I, T: 'a> Iterator for Cloned diff --git a/src/test/ui/specialization/non-defaulted-item-fail.rs b/src/test/ui/specialization/non-defaulted-item-fail.rs deleted file mode 100644 index 403f718d7dd9f..0000000000000 --- a/src/test/ui/specialization/non-defaulted-item-fail.rs +++ /dev/null @@ -1,53 +0,0 @@ -#![feature(specialization, associated_type_defaults)] - -// Test that attempting to override a non-default method or one not in the -// parent impl causes an error. - -trait Foo { - type Ty = (); - const CONST: u8 = 123; - fn foo(&self) -> bool { true } -} - -// Specialization tree for Foo: -// -// Box Vec -// / \ / \ -// Box Box Vec<()> Vec - -impl Foo for Box { - type Ty = bool; - const CONST: u8 = 0; - fn foo(&self) -> bool { false } -} - -// Allowed -impl Foo for Box {} - -// Can't override a non-`default` fn -impl Foo for Box { - type Ty = Vec<()>; -//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` - const CONST: u8 = 42; -//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` - fn foo(&self) -> bool { true } -//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` -} - - -// Doesn't mention the item = provided body/value is used and the method is final. -impl Foo for Vec {} - -// Allowed -impl Foo for Vec<()> {} - -impl Foo for Vec { - type Ty = Vec<()>; -//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` - const CONST: u8 = 42; -//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` - fn foo(&self) -> bool { true } -//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` -} - -fn main() {} diff --git a/src/test/ui/specialization/non-defaulted-item-fail.stderr b/src/test/ui/specialization/non-defaulted-item-fail.stderr deleted file mode 100644 index e6c5fc1441b2f..0000000000000 --- a/src/test/ui/specialization/non-defaulted-item-fail.stderr +++ /dev/null @@ -1,81 +0,0 @@ -error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/non-defaulted-item-fail.rs:29:5 - | -LL | / impl Foo for Box { -LL | | type Ty = bool; -LL | | const CONST: u8 = 0; -LL | | fn foo(&self) -> bool { false } -LL | | } - | |_- parent `impl` is here -... -LL | type Ty = Vec<()>; - | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` - | - = note: to specialize, `Ty` in the parent `impl` must be marked `default` - -error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/non-defaulted-item-fail.rs:31:5 - | -LL | / impl Foo for Box { -LL | | type Ty = bool; -LL | | const CONST: u8 = 0; -LL | | fn foo(&self) -> bool { false } -LL | | } - | |_- parent `impl` is here -... -LL | const CONST: u8 = 42; - | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` - | - = note: to specialize, `CONST` in the parent `impl` must be marked `default` - -error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/non-defaulted-item-fail.rs:33:5 - | -LL | / impl Foo for Box { -LL | | type Ty = bool; -LL | | const CONST: u8 = 0; -LL | | fn foo(&self) -> bool { false } -LL | | } - | |_- parent `impl` is here -... -LL | fn foo(&self) -> bool { true } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` - | - = note: to specialize, `foo` in the parent `impl` must be marked `default` - -error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/non-defaulted-item-fail.rs:45:5 - | -LL | impl Foo for Vec {} - | ------------------------- parent `impl` is here -... -LL | type Ty = Vec<()>; - | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` - | - = note: to specialize, `Ty` in the parent `impl` must be marked `default` - -error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/non-defaulted-item-fail.rs:47:5 - | -LL | impl Foo for Vec {} - | ------------------------- parent `impl` is here -... -LL | const CONST: u8 = 42; - | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` - | - = note: to specialize, `CONST` in the parent `impl` must be marked `default` - -error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/non-defaulted-item-fail.rs:49:5 - | -LL | impl Foo for Vec {} - | ------------------------- parent `impl` is here -... -LL | fn foo(&self) -> bool { true } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` - | - = note: to specialize, `foo` in the parent `impl` must be marked `default` - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0520`. diff --git a/src/test/ui/specialization/specialization-default-methods.rs b/src/test/ui/specialization/specialization-default-methods.rs index 9ae3d1e9f3931..5d65a0457e791 100644 --- a/src/test/ui/specialization/specialization-default-methods.rs +++ b/src/test/ui/specialization/specialization-default-methods.rs @@ -55,9 +55,8 @@ trait Bar { // / \ // Vec $Vec -impl Bar for T { - default fn bar(&self) -> i32 { 0 } -} +// use the provided method +impl Bar for T {} impl Bar for i32 { fn bar(&self) -> i32 { 1 } diff --git a/src/test/ui/static/static-closures.stderr b/src/test/ui/static/static-closures.stderr index 99235e26e15e7..ced78c03e09d6 100644 --- a/src/test/ui/static/static-closures.stderr +++ b/src/test/ui/static/static-closures.stderr @@ -6,4 +6,3 @@ LL | static || {}; error: aborting due to previous error -For more information about this error, try `rustc --explain E0697`. diff --git a/src/test/ui/static/static-drop-scope.stderr b/src/test/ui/static/static-drop-scope.stderr index bc08f33f82093..8a23dad1ba3ea 100644 --- a/src/test/ui/static/static-drop-scope.stderr +++ b/src/test/ui/static/static-drop-scope.stderr @@ -68,5 +68,4 @@ LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; error: aborting due to 10 previous errors -Some errors have detailed explanations: E0493, E0716. -For more information about an error, try `rustc --explain E0493`. +For more information about this error, try `rustc --explain E0716`. diff --git a/src/test/ui/static/static-lifetime.stderr b/src/test/ui/static/static-lifetime.stderr index bda325dc01160..8516ac07b6cf3 100644 --- a/src/test/ui/static/static-lifetime.stderr +++ b/src/test/ui/static/static-lifetime.stderr @@ -4,7 +4,7 @@ error[E0478]: lifetime bound not satisfied LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} | ^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the impl at 3:6 +note: lifetime parameter instantiated with the lifetime 'a as defined on the impl at 3:6 --> $DIR/static-lifetime.rs:3:6 | LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} diff --git a/src/test/ui/struct-literal-variant-in-if.stderr b/src/test/ui/struct-literal-variant-in-if.stderr index a52ec6dc53938..85cbc787bc2db 100644 --- a/src/test/ui/struct-literal-variant-in-if.stderr +++ b/src/test/ui/struct-literal-variant-in-if.stderr @@ -50,10 +50,7 @@ error[E0308]: mismatched types --> $DIR/struct-literal-variant-in-if.rs:10:20 | LL | if x == E::V { field } {} - | ---------------^^^^^--- help: consider using a semicolon here - | | | - | | expected (), found bool - | expected this to be `()` + | ^^^^^ expected (), found bool | = note: expected type `()` found type `bool` diff --git a/src/test/ui/structs-enums/rec-align-u64.rs b/src/test/ui/structs-enums/rec-align-u64.rs index 680a690ba34e3..c4e9e9ea5ee1a 100644 --- a/src/test/ui/structs-enums/rec-align-u64.rs +++ b/src/test/ui/structs-enums/rec-align-u64.rs @@ -40,8 +40,7 @@ struct Outer { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris", - target_os = "vxworks"))] + target_os = "solaris"))] mod m { #[cfg(target_arch = "x86")] pub mod m { diff --git a/src/test/ui/suggestions/constrain-trait.fixed b/src/test/ui/suggestions/constrain-trait.fixed deleted file mode 100644 index dda9e931353b2..0000000000000 --- a/src/test/ui/suggestions/constrain-trait.fixed +++ /dev/null @@ -1,47 +0,0 @@ -// run-rustfix -// check-only - -#[derive(Debug)] -struct Demo { - a: String -} - -trait GetString { - fn get_a(&self) -> &String; -} - -trait UseString: std::fmt::Debug + GetString { - fn use_string(&self) { - println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self` - } -} - -trait UseString2: GetString { - fn use_string(&self) { - println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self` - } -} - -impl GetString for Demo { - fn get_a(&self) -> &String { - &self.a - } -} - -impl UseString for Demo {} -impl UseString2 for Demo {} - - -#[cfg(test)] -mod tests { - use crate::{Demo, UseString}; - - #[test] - fn it_works() { - let d = Demo { a: "test".to_string() }; - d.use_string(); - } -} - - -fn main() {} diff --git a/src/test/ui/suggestions/constrain-trait.rs b/src/test/ui/suggestions/constrain-trait.rs deleted file mode 100644 index 4ef0eff5bd769..0000000000000 --- a/src/test/ui/suggestions/constrain-trait.rs +++ /dev/null @@ -1,47 +0,0 @@ -// run-rustfix -// check-only - -#[derive(Debug)] -struct Demo { - a: String -} - -trait GetString { - fn get_a(&self) -> &String; -} - -trait UseString: std::fmt::Debug { - fn use_string(&self) { - println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self` - } -} - -trait UseString2 { - fn use_string(&self) { - println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self` - } -} - -impl GetString for Demo { - fn get_a(&self) -> &String { - &self.a - } -} - -impl UseString for Demo {} -impl UseString2 for Demo {} - - -#[cfg(test)] -mod tests { - use crate::{Demo, UseString}; - - #[test] - fn it_works() { - let d = Demo { a: "test".to_string() }; - d.use_string(); - } -} - - -fn main() {} diff --git a/src/test/ui/suggestions/constrain-trait.stderr b/src/test/ui/suggestions/constrain-trait.stderr deleted file mode 100644 index 3cc351ac80aed..0000000000000 --- a/src/test/ui/suggestions/constrain-trait.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0599]: no method named `get_a` found for type `&Self` in the current scope - --> $DIR/constrain-trait.rs:15:31 - | -LL | println!("{:?}", self.get_a()); - | ^^^^^ method not found in `&Self` - | - = help: items from traits can only be used if the type parameter is bounded by the trait -help: the following trait defines an item `get_a`, perhaps you need to add another supertrait for it: - | -LL | trait UseString: std::fmt::Debug + GetString { - | ^^^^^^^^^^^ - -error[E0599]: no method named `get_a` found for type `&Self` in the current scope - --> $DIR/constrain-trait.rs:21:31 - | -LL | println!("{:?}", self.get_a()); - | ^^^^^ method not found in `&Self` - | - = help: items from traits can only be used if the type parameter is bounded by the trait -help: the following trait defines an item `get_a`, perhaps you need to add a supertrait for it: - | -LL | trait UseString2: GetString { - | ^^^^^^^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0599`. 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 1af0f7a191e80..28b331bdbdcbc 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 @@ -1,9 +1,6 @@ error[E0423]: expected value, found struct variant `E::B` --> $DIR/fn-or-tuple-struct-without-args.rs:36:16 | -LL | B { a: usize }, - | -------------- `E::B` defined here -... LL | let _: E = E::B; | ^^^- | | | diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.rs b/src/test/ui/suggestions/imm-ref-trait-object-literal.rs deleted file mode 100644 index 22ca6dde45eee..0000000000000 --- a/src/test/ui/suggestions/imm-ref-trait-object-literal.rs +++ /dev/null @@ -1,14 +0,0 @@ -trait Trait {} - -struct S; - -impl<'a> Trait for &'a mut S {} - -fn foo(_: X) {} - - -fn main() { - let s = S; - foo(&s); //~ ERROR the trait bound `&S: Trait` is not satisfied - foo(s); //~ ERROR the trait bound `S: Trait` is not satisfied -} diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr deleted file mode 100644 index ccaceefacd739..0000000000000 --- a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error[E0277]: the trait bound `&S: Trait` is not satisfied - --> $DIR/imm-ref-trait-object-literal.rs:12:7 - | -LL | fn foo(_: X) {} - | --- ----- required by this bound in `foo` -... -LL | foo(&s); - | -^ - | | - | the trait `Trait` is not implemented for `&S` - | help: consider changing this borrow's mutability: `&mut` - | - = help: the following implementations were found: - <&'a mut S as Trait> - -error[E0277]: the trait bound `S: Trait` is not satisfied - --> $DIR/imm-ref-trait-object-literal.rs:13:7 - | -LL | fn foo(_: X) {} - | --- ----- required by this bound in `foo` -... -LL | foo(s); - | ^ the trait `Trait` is not implemented for `S` - | - = help: the following implementations were found: - <&'a mut S as Trait> - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/imm-ref-trait-object.rs b/src/test/ui/suggestions/imm-ref-trait-object.rs deleted file mode 100644 index 288d6c699f59a..0000000000000 --- a/src/test/ui/suggestions/imm-ref-trait-object.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn test(t: &dyn Iterator) -> u64 { - t.min().unwrap() //~ ERROR the `min` method cannot be invoked on a trait object -} - -fn main() { - let array = [0u64]; - test(&mut array.iter()); -} diff --git a/src/test/ui/suggestions/imm-ref-trait-object.stderr b/src/test/ui/suggestions/imm-ref-trait-object.stderr deleted file mode 100644 index 9185eaa65c06d..0000000000000 --- a/src/test/ui/suggestions/imm-ref-trait-object.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: the `min` method cannot be invoked on a trait object - --> $DIR/imm-ref-trait-object.rs:2:8 - | -LL | t.min().unwrap() - | ^^^ - | - = note: you need `&mut dyn std::iter::Iterator` instead of `&dyn std::iter::Iterator` - -error: aborting due to previous error - diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index a1e1f4d13572a..fb3e1096ad54c 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -8,7 +8,6 @@ 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: `std::convert::From` is implemented for `&mut str`, but not for `&str` = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String` error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-61226.stderr b/src/test/ui/suggestions/issue-61226.stderr index fbcfba6653f27..6d7d98ac6a16b 100644 --- a/src/test/ui/suggestions/issue-61226.stderr +++ b/src/test/ui/suggestions/issue-61226.stderr @@ -1,9 +1,6 @@ error[E0423]: expected value, found struct `X` --> $DIR/issue-61226.rs:3:10 | -LL | struct X {} - | ----------- `X` defined here -LL | fn main() { LL | vec![X]; //… | ^ did you mean `X { /* fields */ }`? diff --git a/src/test/ui/suggestions/issue-64252-self-type.rs b/src/test/ui/suggestions/issue-64252-self-type.rs deleted file mode 100644 index 128d5e85c22c8..0000000000000 --- a/src/test/ui/suggestions/issue-64252-self-type.rs +++ /dev/null @@ -1,14 +0,0 @@ -// This test checks that a suggestion to add a `self: ` parameter name is provided -// to functions where this is applicable. - -pub fn foo(Box) { } -//~^ ERROR expected one of `:`, `@`, or `|`, found `<` - -struct Bar; - -impl Bar { - fn bar(Box) { } - //~^ ERROR expected one of `:`, `@`, or `|`, found `<` -} - -fn main() { } diff --git a/src/test/ui/suggestions/issue-64252-self-type.stderr b/src/test/ui/suggestions/issue-64252-self-type.stderr deleted file mode 100644 index fa28a0d684e5e..0000000000000 --- a/src/test/ui/suggestions/issue-64252-self-type.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error: expected one of `:`, `@`, or `|`, found `<` - --> $DIR/issue-64252-self-type.rs:4:15 - | -LL | pub fn foo(Box) { } - | ^ expected one of `:`, `@`, or `|` here - | - = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this is a type, explicitly ignore the parameter name - | -LL | pub fn foo(_: Box) { } - | ^^^^^^ - -error: expected one of `:`, `@`, or `|`, found `<` - --> $DIR/issue-64252-self-type.rs:10:15 - | -LL | fn bar(Box) { } - | ^ expected one of `:`, `@`, or `|` here - | - = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this is a `self` type, give it a parameter name - | -LL | fn bar(self: Box) { } - | ^^^^^^^^^ -help: if this is a type, explicitly ignore the parameter name - | -LL | fn bar(_: Box) { } - | ^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/suggestions/match-needing-semi.fixed b/src/test/ui/suggestions/match-needing-semi.fixed deleted file mode 100644 index 03cbed1376ea3..0000000000000 --- a/src/test/ui/suggestions/match-needing-semi.fixed +++ /dev/null @@ -1,18 +0,0 @@ -// check-only -// run-rustfix - -fn main() { - match 3 { - 4 => 1, - 3 => { - 2 //~ ERROR mismatched types - } - _ => 2 - }; - match 3 { //~ ERROR mismatched types - 4 => 1, - 3 => 2, - _ => 2 - }; - let _ = (); -} diff --git a/src/test/ui/suggestions/match-needing-semi.rs b/src/test/ui/suggestions/match-needing-semi.rs deleted file mode 100644 index f34071ac75886..0000000000000 --- a/src/test/ui/suggestions/match-needing-semi.rs +++ /dev/null @@ -1,18 +0,0 @@ -// check-only -// run-rustfix - -fn main() { - match 3 { - 4 => 1, - 3 => { - 2 //~ ERROR mismatched types - } - _ => 2 - } - match 3 { //~ ERROR mismatched types - 4 => 1, - 3 => 2, - _ => 2 - } - let _ = (); -} diff --git a/src/test/ui/suggestions/match-needing-semi.stderr b/src/test/ui/suggestions/match-needing-semi.stderr deleted file mode 100644 index 988945817c2ee..0000000000000 --- a/src/test/ui/suggestions/match-needing-semi.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/match-needing-semi.rs:8:13 - | -LL | / match 3 { -LL | | 4 => 1, -LL | | 3 => { -LL | | 2 - | | ^ expected (), found integer -LL | | } -LL | | _ => 2 -LL | | } - | | -- help: consider using a semicolon here - | |_____| - | expected this to be `()` - | - = note: expected type `()` - found type `{integer}` - -error[E0308]: mismatched types - --> $DIR/match-needing-semi.rs:12:5 - | -LL | / match 3 { -LL | | 4 => 1, -LL | | 3 => 2, -LL | | _ => 2 -LL | | } - | | ^- help: consider using a semicolon here - | |_____| - | expected (), found integer - | - = note: expected type `()` - found type `{integer}` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs deleted file mode 100644 index 265ccb3125ca3..0000000000000 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Running rustfix would cause the same suggestion to be applied multiple times, which results in -// invalid code. - -trait Parent { - type Ty; - type Assoc: Child; -} - -trait Child {} - -struct ChildWrapper(T); - -impl Child for ChildWrapper where T: Child {} - -struct ParentWrapper(T); - -impl> Parent for ParentWrapper { - //~^ ERROR the trait bound `::Assoc: Child` is not satisfied - //~| ERROR the trait bound `::Assoc: Child` is not satisfied - type Ty = A; - type Assoc = ChildWrapper; - //~^ ERROR the trait bound `::Assoc: Child` is not satisfied -} - -fn main() {} diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr deleted file mode 100644 index bdea8ab97e5b5..0000000000000 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:17:1 - | -LL | trait Parent { - | ------------ required by `Parent` -... -LL | impl> Parent for ParentWrapper { - | ^ - help: consider further restricting the associated type: `where ::Assoc: Child` - | _| - | | -LL | | -LL | | -LL | | type Ty = A; -LL | | type Assoc = ChildWrapper; -LL | | -LL | | } - | |_^ the trait `Child` is not implemented for `::Assoc` - -error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:17:28 - | -LL | impl> Parent for ParentWrapper { - | ^^^^^^ - help: consider further restricting the associated type: `where ::Assoc: Child` - | | - | the trait `Child` is not implemented for `::Assoc` - | - = note: required because of the requirements on the impl of `Child` for `ChildWrapper<::Assoc>` - -error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:21:5 - | -LL | trait Parent { - | ------------ required by `Parent` -... -LL | impl> Parent for ParentWrapper { - | - help: consider further restricting the associated type: `where ::Assoc: Child` -... -LL | type Assoc = ChildWrapper; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child` is not implemented for `::Assoc` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs deleted file mode 100644 index dcef2ada63bea..0000000000000 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::env::args; -use std::fs::File; -use std::io::{stdout, Write, BufWriter}; - -fn main() { - let mut args = args(); - let _ = args.next(); - let dest = args.next(); - - let h1; let h2; let h3; - - let fp: &dyn Write = match dest { - Some(path) => { h1 = File::create(path).unwrap(); &h1 }, - None => { h2 = stdout(); h3 = h2.lock(); &h3 } - }; - - let fp = BufWriter::new(fp); - //~^ ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - - writeln!(fp, "hello world").unwrap(); //~ ERROR no method named `write_fmt` found for type -} diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr deleted file mode 100644 index daa8e1162d197..0000000000000 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ /dev/null @@ -1,41 +0,0 @@ -error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:17:29 - | -LL | let fp = BufWriter::new(fp); - | ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` - | - = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` - = note: required by `std::io::BufWriter::::new` - -error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:17:14 - | -LL | let fp = BufWriter::new(fp); - | ^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` - | - = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` - = note: required by `std::io::BufWriter` - -error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:17:14 - | -LL | let fp = BufWriter::new(fp); - | ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` - | - = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` - = note: required by `std::io::BufWriter` - -error[E0599]: no method named `write_fmt` found for type `std::io::BufWriter<&dyn std::io::Write>` in the current scope - --> $DIR/mut-borrow-needed-by-trait.rs:22:5 - | -LL | writeln!(fp, "hello world").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::io::BufWriter<&dyn std::io::Write>` - | - = note: the method `write_fmt` exists but the following trait bounds were not satisfied: - `std::io::BufWriter<&dyn std::io::Write> : std::io::Write` - = 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 4 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/suggestions/remove-as_str.rs b/src/test/ui/suggestions/remove-as_str.rs deleted file mode 100644 index d10300b48ba1e..0000000000000 --- a/src/test/ui/suggestions/remove-as_str.rs +++ /dev/null @@ -1,21 +0,0 @@ -fn foo1(s: &str) { - s.as_str(); - //~^ ERROR no method named `as_str` found for type `&str` in the current scope -} - -fn foo2<'a>(s: &'a str) { - s.as_str(); - //~^ ERROR no method named `as_str` found for type `&'a str` in the current scope -} - -fn foo3(s: &mut str) { - s.as_str(); - //~^ ERROR no method named `as_str` found for type `&mut str` in the current scope -} - -fn foo4(s: &&str) { - s.as_str(); - //~^ ERROR no method named `as_str` found for type `&&str` in the current scope -} - -fn main() {} diff --git a/src/test/ui/suggestions/remove-as_str.stderr b/src/test/ui/suggestions/remove-as_str.stderr deleted file mode 100644 index eae9cc075084a..0000000000000 --- a/src/test/ui/suggestions/remove-as_str.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0599]: no method named `as_str` found for type `&str` in the current scope - --> $DIR/remove-as_str.rs:2:7 - | -LL | s.as_str(); - | -^^^^^^-- help: remove this method call - -error[E0599]: no method named `as_str` found for type `&'a str` in the current scope - --> $DIR/remove-as_str.rs:7:7 - | -LL | s.as_str(); - | -^^^^^^-- help: remove this method call - -error[E0599]: no method named `as_str` found for type `&mut str` in the current scope - --> $DIR/remove-as_str.rs:12:7 - | -LL | s.as_str(); - | -^^^^^^-- help: remove this method call - -error[E0599]: no method named `as_str` found for type `&&str` in the current scope - --> $DIR/remove-as_str.rs:17:7 - | -LL | s.as_str(); - | -^^^^^^-- help: remove this method call - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/restrict-type-argument.rs b/src/test/ui/suggestions/restrict-type-argument.rs deleted file mode 100644 index c4ebfbe922c09..0000000000000 --- a/src/test/ui/suggestions/restrict-type-argument.rs +++ /dev/null @@ -1,31 +0,0 @@ -fn is_send(val: T) {} - -fn use_impl_sync(val: impl Sync) { - is_send(val); //~ ERROR `impl Sync` cannot be sent between threads safely -} - -fn use_where(val: S) where S: Sync { - is_send(val); //~ ERROR `S` cannot be sent between threads safely -} - -fn use_bound(val: S) { - is_send(val); //~ ERROR `S` cannot be sent between threads safely -} - -fn use_bound_2< - S // Make sure we can synthezise a correct suggestion span for this case - : - Sync ->(val: S) { - is_send(val); //~ ERROR `S` cannot be sent between threads safely -} - -fn use_bound_and_where(val: S) where S: std::fmt::Debug { - is_send(val); //~ ERROR `S` cannot be sent between threads safely -} - -fn use_unbound(val: S) { - is_send(val); //~ ERROR `S` cannot be sent between threads safely -} - -fn main() {} diff --git a/src/test/ui/suggestions/restrict-type-argument.stderr b/src/test/ui/suggestions/restrict-type-argument.stderr deleted file mode 100644 index d6840ca4d7265..0000000000000 --- a/src/test/ui/suggestions/restrict-type-argument.stderr +++ /dev/null @@ -1,83 +0,0 @@ -error[E0277]: `impl Sync` cannot be sent between threads safely - --> $DIR/restrict-type-argument.rs:4:13 - | -LL | fn is_send(val: T) {} - | ------- ---- required by this bound in `is_send` -LL | -LL | fn use_impl_sync(val: impl Sync) { - | --------- help: consider further restricting this bound: `impl Sync + std::marker::Send` -LL | is_send(val); - | ^^^ `impl Sync` cannot be sent between threads safely - | - = help: the trait `std::marker::Send` is not implemented for `impl Sync` - -error[E0277]: `S` cannot be sent between threads safely - --> $DIR/restrict-type-argument.rs:8:13 - | -LL | fn is_send(val: T) {} - | ------- ---- required by this bound in `is_send` -... -LL | fn use_where(val: S) where S: Sync { - | - help: consider further restricting type parameter `S`: `, S: std::marker::Send` -LL | is_send(val); - | ^^^ `S` cannot be sent between threads safely - | - = help: the trait `std::marker::Send` is not implemented for `S` - -error[E0277]: `S` cannot be sent between threads safely - --> $DIR/restrict-type-argument.rs:12:13 - | -LL | fn is_send(val: T) {} - | ------- ---- required by this bound in `is_send` -... -LL | fn use_bound(val: S) { - | -- help: consider further restricting this bound: `S: std::marker::Send +` -LL | is_send(val); - | ^^^ `S` cannot be sent between threads safely - | - = help: the trait `std::marker::Send` is not implemented for `S` - -error[E0277]: `S` cannot be sent between threads safely - --> $DIR/restrict-type-argument.rs:20:13 - | -LL | fn is_send(val: T) {} - | ------- ---- required by this bound in `is_send` -... -LL | / S // Make sure we can synthezise a correct suggestion span for this case -LL | | : - | |_____- help: consider further restricting this bound: `S: std::marker::Send +` -... -LL | is_send(val); - | ^^^ `S` cannot be sent between threads safely - | - = help: the trait `std::marker::Send` is not implemented for `S` - -error[E0277]: `S` cannot be sent between threads safely - --> $DIR/restrict-type-argument.rs:24:13 - | -LL | fn is_send(val: T) {} - | ------- ---- required by this bound in `is_send` -... -LL | fn use_bound_and_where(val: S) where S: std::fmt::Debug { - | - help: consider further restricting type parameter `S`: `, S: std::marker::Send` -LL | is_send(val); - | ^^^ `S` cannot be sent between threads safely - | - = help: the trait `std::marker::Send` is not implemented for `S` - -error[E0277]: `S` cannot be sent between threads safely - --> $DIR/restrict-type-argument.rs:28:13 - | -LL | fn is_send(val: T) {} - | ------- ---- required by this bound in `is_send` -... -LL | fn use_unbound(val: S) { - | - help: consider restricting this bound: `S: std::marker::Send` -LL | is_send(val); - | ^^^ `S` cannot be sent between threads safely - | - = help: the trait `std::marker::Send` is not implemented for `S` - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs deleted file mode 100644 index 5480adb31015a..0000000000000 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs +++ /dev/null @@ -1,13 +0,0 @@ -use std::cell::RefCell; - -struct HasAssocMethod; - -impl HasAssocMethod { - fn hello() {} -} -fn main() { - let shared_state = RefCell::new(HasAssocMethod); - let state = shared_state.borrow_mut(); - state.hello(); - //~^ ERROR no method named `hello` found for type `std::cell::RefMut<'_, HasAssocMethod>` -} diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr deleted file mode 100644 index a1c0126146e73..0000000000000 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0599]: no method named `hello` found for type `std::cell::RefMut<'_, HasAssocMethod>` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11 - | -LL | state.hello(); - | ------^^^^^ - | | | - | | this is an associated function, not a method - | help: use associated function syntax instead: `HasAssocMethod::hello` - | - = note: found the following associated functions; to be used as methods, functions must have a `self` parameter -note: the candidate is defined in an impl for the type `HasAssocMethod` - --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:6:5 - | -LL | fn hello() {} - | ^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs deleted file mode 100644 index ef4b38de94732..0000000000000 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs +++ /dev/null @@ -1,11 +0,0 @@ -struct GenericAssocMethod(T); - -impl GenericAssocMethod { - fn default_hello() {} -} - -fn main() { - let x = GenericAssocMethod(33i32); - x.default_hello(); - //~^ ERROR no method named `default_hello` found for type `GenericAssocMethod` -} diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr deleted file mode 100644 index 8cfa7de08bb38..0000000000000 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0599]: no method named `default_hello` found for type `GenericAssocMethod` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7 - | -LL | struct GenericAssocMethod(T); - | -------------------------------- method `default_hello` not found for this -... -LL | x.default_hello(); - | --^^^^^^^^^^^^^ - | | | - | | this is an associated function, not a method - | help: use associated function syntax instead: `GenericAssocMethod::::default_hello` - | - = note: found the following associated functions; to be used as methods, functions must have a `self` parameter -note: the candidate is defined in an impl for the type `GenericAssocMethod<_>` - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:4:5 - | -LL | fn default_hello() {} - | ^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/symbol-names/impl1.legacy.stderr b/src/test/ui/symbol-names/impl1.legacy.stderr index 610937739c194..c1d22a919d900 100644 --- a/src/test/ui/symbol-names/impl1.legacy.stderr +++ b/src/test/ui/symbol-names/impl1.legacy.stderr @@ -46,26 +46,26 @@ error: def-path(bar::::baz) LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ -error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17h636bc933fc62ee2fE) - --> $DIR/impl1.rs:61:13 +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$6method17h6f205aef6a8ccc7bE) + --> $DIR/impl1.rs:63:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::h636bc933fc62ee2f) - --> $DIR/impl1.rs:61:13 +error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::h6f205aef6a8ccc7b) + --> $DIR/impl1.rs:63:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method) - --> $DIR/impl1.rs:61:13 +error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method) + --> $DIR/impl1.rs:63:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: def-path(<[&dyn Foo extern "C" fn(&'r u8, ...)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) - --> $DIR/impl1.rs:68:13 +error: def-path(<[&dyn Foo extern "C" fn(&'r u8)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) + --> $DIR/impl1.rs:70:13 | LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs index add0d10ea6cb0..137b72dcd9c44 100644 --- a/src/test/ui/symbol-names/impl1.rs +++ b/src/test/ui/symbol-names/impl1.rs @@ -57,17 +57,19 @@ fn main() { } // Test type mangling, by putting them in an `impl` header. - impl Bar for [&'_ (dyn Foo + AutoTrait); 3] { + // FIXME(eddyb) test C varargs when `core::ffi::VaListImpl` stops leaking into the signature + // (which is a problem because `core` has an unpredictable hash) - see also #44930. + impl Bar for [&'_ (dyn Foo + AutoTrait); 3] { #[rustc_symbol_name] - //[legacy]~^ ERROR symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$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_3Foop5AssocFG_KCRL0_hvEuNtB6_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) + //[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_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) + //[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) fn method(&self) {} } }; diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr index 01fe39ddf6cf9..e024799df867c 100644 --- a/src/test/ui/symbol-names/impl1.v0.stderr +++ b/src/test/ui/symbol-names/impl1.v0.stderr @@ -46,26 +46,26 @@ error: def-path(bar::::baz) LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ -error: symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) - --> $DIR/impl1.rs:61:13 +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(&'a u8, ...)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) - --> $DIR/impl1.rs:61:13 +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(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) - --> $DIR/impl1.rs:61:13 +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] | ^^^^^^^^^^^^^^^^^^^^ -error: def-path(<[&dyn Foo extern "C" fn(&'r u8, ...)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) - --> $DIR/impl1.rs:68:13 +error: def-path(<[&dyn Foo extern "C" fn(&'r u8)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) + --> $DIR/impl1.rs:70:13 | LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/synthetic-param.rs b/src/test/ui/synthetic-param.rs index e14697f5c3e97..e53e3ba06e0d1 100644 --- a/src/test/ui/synthetic-param.rs +++ b/src/test/ui/synthetic-param.rs @@ -17,12 +17,12 @@ impl Bar { } fn main() { - func::(42); //~ ERROR cannot provide explicit generic arguments + func::(42); //~ ERROR cannot provide explicit type parameters func(42); // Ok - Foo::func::(42); //~ ERROR cannot provide explicit generic arguments + Foo::func::(42); //~ ERROR cannot provide explicit type parameters Foo::func(42); // Ok - Bar::::func::(42); //~ ERROR cannot provide explicit generic arguments + Bar::::func::(42); //~ ERROR cannot provide explicit type parameters Bar::::func(42); // Ok } diff --git a/src/test/ui/synthetic-param.stderr b/src/test/ui/synthetic-param.stderr index 951d7edb7f523..bfafd8cbd72ec 100644 --- a/src/test/ui/synthetic-param.stderr +++ b/src/test/ui/synthetic-param.stderr @@ -1,20 +1,20 @@ -error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> $DIR/synthetic-param.rs:20:12 +error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position. + --> $DIR/synthetic-param.rs:20:5 | LL | func::(42); - | ^^ explicit generic argument not allowed + | ^^^^^^^^^^ -error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> $DIR/synthetic-param.rs:23:17 +error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position. + --> $DIR/synthetic-param.rs:23:5 | LL | Foo::func::(42); - | ^^ explicit generic argument not allowed + | ^^^^^^^^^^^^^^^ -error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> $DIR/synthetic-param.rs:26:23 +error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position. + --> $DIR/synthetic-param.rs:26:5 | LL | Bar::::func::(42); - | ^^ explicit generic argument not allowed + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/test-attrs/test-allow-fail-attr.rs b/src/test/ui/test-attrs/test-allow-fail-attr.rs index 55b743ab7c7ea..1a478460efc6c 100644 --- a/src/test/ui/test-attrs/test-allow-fail-attr.rs +++ b/src/test/ui/test-attrs/test-allow-fail-attr.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: --test #![feature(allow_fail)] diff --git a/src/test/ui/test-attrs/test-should-fail-good-message.rs b/src/test/ui/test-attrs/test-should-fail-good-message.rs index 2284953fbbe94..9fa759f9eb483 100644 --- a/src/test/ui/test-attrs/test-should-fail-good-message.rs +++ b/src/test/ui/test-attrs/test-should-fail-good-message.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: --test #[test] #[should_panic(expected = "foo")] diff --git a/src/test/ui/test-panic-abort-disabled.rs b/src/test/ui/test-panic-abort-disabled.rs deleted file mode 100644 index f24046ff0e8d2..0000000000000 --- a/src/test/ui/test-panic-abort-disabled.rs +++ /dev/null @@ -1,20 +0,0 @@ -// error-pattern:building tests with panic=abort is not yet supported -// no-prefer-dynamic -// compile-flags: --test -Cpanic=abort -// run-flags: --test-threads=1 - -// ignore-wasm no panic or subprocess support -// ignore-emscripten no panic or subprocess support - -#![cfg(test)] - -#[test] -fn it_works() { - assert_eq!(1 + 1, 2); -} - -#[test] -#[should_panic] -fn it_panics() { - assert_eq!(1 + 1, 4); -} diff --git a/src/test/ui/test-panic-abort-disabled.stderr b/src/test/ui/test-panic-abort-disabled.stderr deleted file mode 100644 index a8d9bad43ed3c..0000000000000 --- a/src/test/ui/test-panic-abort-disabled.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error: building tests with panic=abort is not yet supported - -error: aborting due to previous error - diff --git a/src/test/ui/test-panic-abort.rs b/src/test/ui/test-panic-abort.rs deleted file mode 100644 index b0679ea1d3df2..0000000000000 --- a/src/test/ui/test-panic-abort.rs +++ /dev/null @@ -1,37 +0,0 @@ -// no-prefer-dynamic -// compile-flags: --test -Cpanic=abort -Zpanic_abort_tests -// run-flags: --test-threads=1 -// run-fail -// check-run-results -// exec-env:RUST_BACKTRACE=0 - -// ignore-wasm no panic or subprocess support -// ignore-emscripten no panic or subprocess support - -#![cfg(test)] - -use std::io::Write; - -#[test] -fn it_works() { - assert_eq!(1 + 1, 2); -} - -#[test] -#[should_panic] -fn it_panics() { - assert_eq!(1 + 1, 4); -} - -#[test] -fn it_fails() { - println!("hello, world"); - writeln!(std::io::stdout(), "testing123").unwrap(); - writeln!(std::io::stderr(), "testing321").unwrap(); - assert_eq!(1 + 1, 5); -} - -#[test] -fn it_exits() { - std::process::exit(123); -} diff --git a/src/test/ui/test-panic-abort.run.stdout b/src/test/ui/test-panic-abort.run.stdout deleted file mode 100644 index 0c8bc5020871b..0000000000000 --- a/src/test/ui/test-panic-abort.run.stdout +++ /dev/null @@ -1,29 +0,0 @@ - -running 4 tests -test it_exits ... FAILED -test it_fails ... FAILED -test it_panics ... ok -test it_works ... ok - -failures: - ----- it_exits stdout ---- ----- it_exits stderr ---- -note: got unexpected return code 123 ----- it_fails stdout ---- -hello, world -testing123 ----- it_fails stderr ---- -testing321 -thread 'main' panicked at 'assertion failed: `(left == right)` - left: `2`, - right: `5`', $DIR/test-panic-abort.rs:31:5 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. - - -failures: - it_exits - it_fails - -test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out - 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 b831e624cb6ff..6bef793e0e71b 100644 --- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr +++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr @@ -42,5 +42,4 @@ LL | rustfmt::skip; error: aborting due to 7 previous errors -Some errors have detailed explanations: E0423, E0573. -For more information about an error, try `rustc --explain E0423`. +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.rs b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.rs index 039bbce8c1ed0..5948d45b6987f 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.rs @@ -4,7 +4,4 @@ trait Foo {} auto trait A = Foo; //~ ERROR trait aliases cannot be `auto` unsafe trait B = Foo; //~ ERROR trait aliases cannot be `unsafe` -trait C: Ord = Eq; //~ ERROR bounds are not allowed on trait aliases -trait D: = Eq; //~ ERROR bounds are not allowed on trait aliases - fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr index 18c22133bc780..f456a2d778c25 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr @@ -1,26 +1,14 @@ error: trait aliases cannot be `auto` - --> $DIR/trait-alias-syntax-fail.rs:4:1 + --> $DIR/trait-alias-syntax-fail.rs:4:19 | LL | auto trait A = Foo; - | ^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `auto` + | ^ trait aliases cannot be `auto` error: trait aliases cannot be `unsafe` - --> $DIR/trait-alias-syntax-fail.rs:5:1 + --> $DIR/trait-alias-syntax-fail.rs:5:21 | LL | unsafe trait B = Foo; - | ^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `unsafe` + | ^ trait aliases cannot be `unsafe` -error: bounds are not allowed on trait aliases - --> $DIR/trait-alias-syntax-fail.rs:7:8 - | -LL | trait C: Ord = Eq; - | ^^^^^ - -error: bounds are not allowed on trait aliases - --> $DIR/trait-alias-syntax-fail.rs:8:8 - | -LL | trait D: = Eq; - | ^ - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors 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 4355a517bd724..ca6d058471667 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-wf.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-wf.stderr @@ -4,10 +4,9 @@ error[E0277]: the trait bound `T: Foo` is not satisfied LL | trait A {} | --------------- required by `A` LL | trait B = A; - | ^^^^^^^^-^^^^^^^^^ - | | | - | | help: consider restricting this bound: `T: Foo` - | the trait `Foo` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T` + | + = help: consider adding a `where T: Foo` bound error: aborting due to previous error diff --git a/src/test/ui/traits/trait-as-struct-constructor.stderr b/src/test/ui/traits/trait-as-struct-constructor.stderr index e1d54fbf8aa7b..434dcbc8736aa 100644 --- a/src/test/ui/traits/trait-as-struct-constructor.stderr +++ b/src/test/ui/traits/trait-as-struct-constructor.stderr @@ -6,4 +6,3 @@ LL | TraitNotAStruct{ value: 0 }; error: aborting due to previous error -For more information about this error, try `rustc --explain E0574`. 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 96bbd1f3e4f17..bd76df8071a53 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 @@ -5,9 +5,9 @@ LL | struct Foo { | ------------------- required by `Foo` ... LL | impl Foo { - | - ^^^^^^ the trait `Trait` is not implemented for `T` - | | - | help: consider restricting this bound: `T: Trait` + | ^^^^^^ the trait `Trait` is not implemented for `T` + | + = help: consider adding a `where T: Trait` bound error[E0277]: the trait bound `isize: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:19:5 @@ -33,10 +33,10 @@ error[E0277]: the trait bound `U: Trait` is not satisfied LL | struct Foo { | ------------------- required by `Foo` ... -LL | struct Badness { - | - help: consider restricting this bound: `U: Trait` LL | b: Foo, | ^^^^^^^^^ the trait `Trait` is not implemented for `U` + | + = help: consider adding a `where U: Trait` bound error[E0277]: the trait bound `V: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:31:21 @@ -44,10 +44,10 @@ error[E0277]: the trait bound `V: Trait` is not satisfied LL | enum Bar { | ----------------- required by `Bar` ... -LL | enum MoreBadness { - | - help: consider restricting this bound: `V: Trait` LL | EvenMoreBadness(Bar), | ^^^^^^ the trait `Trait` is not implemented for `V` + | + = help: consider adding a `where V: Trait` bound error[E0277]: the trait bound `i32: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:35:5 diff --git a/src/test/ui/traits/trait-impl-for-module.stderr b/src/test/ui/traits/trait-impl-for-module.stderr index c62bcfca94de9..4a06cd777d49e 100644 --- a/src/test/ui/traits/trait-impl-for-module.stderr +++ b/src/test/ui/traits/trait-impl-for-module.stderr @@ -6,4 +6,3 @@ LL | impl A for a { error: aborting due to previous error -For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr index 88c9c473eb0c7..fb417b82d15ce 100644 --- a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr +++ b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr @@ -4,12 +4,12 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` d LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { | ^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 24:6... +note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 24:6... --> $DIR/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:6 | LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { | ^^ -note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the impl at 24:9... +note: ...but the lifetime must also be valid for the lifetime 'b as defined on the impl at 24:9... --> $DIR/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:9 | LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { @@ -20,4 +20,3 @@ LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index 64a92c6b0b478..39cc66d275c24 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -28,7 +28,7 @@ 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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use method::B; | @@ -62,7 +62,7 @@ LL | S::b(&S); | ^ function or associated item 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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use method::B; | @@ -96,7 +96,7 @@ LL | S::B; | ^ associated item 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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use assoc_const::B; | diff --git a/src/test/ui/traits/trait-matching-lifetimes.stderr b/src/test/ui/traits/trait-matching-lifetimes.stderr index e1ccde3c9d14a..80c577674d166 100644 --- a/src/test/ui/traits/trait-matching-lifetimes.stderr +++ b/src/test/ui/traits/trait-matching-lifetimes.stderr @@ -6,12 +6,12 @@ LL | fn foo(x: Foo<'b,'a>) { | = note: expected type `fn(Foo<'a, 'b>)` found type `fn(Foo<'b, 'a>)` -note: the lifetime `'b` as defined on the impl at 13:9... +note: the lifetime 'b as defined on the impl at 13:9... --> $DIR/trait-matching-lifetimes.rs:13:9 | LL | impl<'a,'b> Tr for Foo<'a,'b> { | ^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 13:6 +note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 13:6 --> $DIR/trait-matching-lifetimes.rs:13:6 | LL | impl<'a,'b> Tr for Foo<'a,'b> { @@ -25,12 +25,12 @@ LL | fn foo(x: Foo<'b,'a>) { | = note: expected type `fn(Foo<'a, 'b>)` found type `fn(Foo<'b, 'a>)` -note: the lifetime `'a` as defined on the impl at 13:6... +note: the lifetime 'a as defined on the impl at 13:6... --> $DIR/trait-matching-lifetimes.rs:13:6 | LL | impl<'a,'b> Tr for Foo<'a,'b> { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 13:9 +note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 13:9 --> $DIR/trait-matching-lifetimes.rs:13:9 | LL | impl<'a,'b> Tr for Foo<'a,'b> { diff --git a/src/test/ui/traits/trait-method-private.stderr b/src/test/ui/traits/trait-method-private.stderr index 10552acb348be..c1dd9387ebc48 100644 --- a/src/test/ui/traits/trait-method-private.stderr +++ b/src/test/ui/traits/trait-method-private.stderr @@ -5,7 +5,7 @@ LL | foo.method(); | ^^^^^^ | = 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: +help: the following trait is implemented but not in scope, perhaps add a `use` for it: | LL | use inner::Bar; | diff --git a/src/test/ui/traits/trait-object-safety.stderr b/src/test/ui/traits/trait-object-safety.stderr index 028e9eedd641a..3ac1e96b30c95 100644 --- a/src/test/ui/traits/trait-object-safety.stderr +++ b/src/test/ui/traits/trait-object-safety.stderr @@ -8,7 +8,6 @@ LL | let _: &dyn Tr = &St; | ^^^ the trait `Tr` cannot be made into an object | = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St` - = note: required by cast to type `&dyn Tr` error[E0038]: the trait `Tr` cannot be made into an object --> $DIR/trait-object-safety.rs:15:12 diff --git a/src/test/ui/traits/trait-suggest-where-clause.stderr b/src/test/ui/traits/trait-suggest-where-clause.stderr index f1004ea9dc6ee..d15edaa9c8146 100644 --- a/src/test/ui/traits/trait-suggest-where-clause.stderr +++ b/src/test/ui/traits/trait-suggest-where-clause.stderr @@ -1,9 +1,6 @@ error[E0277]: the size for values of type `U` cannot be known at compilation time --> $DIR/trait-suggest-where-clause.rs:9:20 | -LL | fn check() { - | -- help: consider further restricting this bound: `U: std::marker::Sized +` -LL | // suggest a where-clause, if needed LL | mem::size_of::(); | ^ doesn't have a size known at compile-time | @@ -14,13 +11,11 @@ LL | pub const fn size_of() -> usize { | = 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 error[E0277]: the size for values of type `U` cannot be known at compilation time --> $DIR/trait-suggest-where-clause.rs:12:5 | -LL | fn check() { - | -- help: consider further restricting this bound: `U: std::marker::Sized +` -... LL | mem::size_of::>(); | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | @@ -31,6 +26,7 @@ LL | pub const fn size_of() -> usize { | = 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` error[E0277]: the trait bound `u64: std::convert::From` is not satisfied @@ -39,6 +35,7 @@ error[E0277]: the trait bound `u64: std::convert::From` is not satisfied LL | >::from; | ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `u64` | + = help: consider adding a `where u64: std::convert::From` bound = note: required by `std::convert::From::from` error[E0277]: the trait bound `u64: std::convert::From<::Item>` is not satisfied @@ -47,6 +44,7 @@ error[E0277]: the trait bound `u64: std::convert::From<::Item>>::from; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<::Item>` is not implemented for `u64` | + = help: consider adding a `where u64: std::convert::From<::Item>` bound = note: required by `std::convert::From::from` error[E0277]: the trait bound `Misc<_>: std::convert::From` is not satisfied diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr index 9b750d382ec96..83c2c06527493 100644 --- a/src/test/ui/traits/trait-test-2.stderr +++ b/src/test/ui/traits/trait-test-2.stderr @@ -33,7 +33,6 @@ LL | (box 10 as Box).dup(); | ^^^^^^ the trait `bar` cannot be made into an object | = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box<{integer}>` - = note: required by cast to type `std::boxed::Box` error: aborting due to 4 previous errors 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 63182a6bd9581..40c2c2e4c9d10 100644 --- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr @@ -17,5 +17,4 @@ LL | let (a, b) = copy(NoClone); error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0568. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr b/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr index 85c7a55c31379..db77e82adbd00 100644 --- a/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr +++ b/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr @@ -7,10 +7,10 @@ LL | c.same_as(22) error[E0277]: the trait bound `C: CompareTo` is not satisfied --> $DIR/traits-repeated-supertrait-ambig.rs:30:7 | -LL | fn with_trait(c: &C) -> bool { - | -- help: consider further restricting this bound: `C: CompareTo +` LL | c.same_as(22) | ^^^^^^^ the trait `CompareTo` is not implemented for `C` + | + = help: consider adding a `where C: CompareTo` bound error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfied --> $DIR/traits-repeated-supertrait-ambig.rs:34:5 @@ -27,10 +27,10 @@ error[E0277]: the trait bound `C: CompareTo` is not satisfied LL | fn same_as(&self, t: T) -> bool; | -------------------------------- required by `CompareTo::same_as` ... -LL | fn with_ufcs2(c: &C) -> bool { - | -- help: consider further restricting this bound: `C: CompareTo +` LL | CompareTo::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^ the trait `CompareTo` is not implemented for `C` + | + = help: consider adding a `where C: CompareTo` bound error[E0277]: the trait bound `i64: CompareTo` is not satisfied --> $DIR/traits-repeated-supertrait-ambig.rs:42:23 diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr index c94e43131faf0..7034cdce7553d 100644 --- a/src/test/ui/try-block/try-block-in-edition2015.stderr +++ b/src/test/ui/try-block/try-block-in-edition2015.stderr @@ -21,4 +21,3 @@ LL | let try_result: Option<_> = try { error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/try-block/try-block-unreachable-code-lint.rs b/src/test/ui/try-block/try-block-unreachable-code-lint.rs deleted file mode 100644 index 5a9f662d229b2..0000000000000 --- a/src/test/ui/try-block/try-block-unreachable-code-lint.rs +++ /dev/null @@ -1,76 +0,0 @@ -// Test unreachable_code lint for `try {}` block ok-wrapping. See issues #54165, #63324. - -// compile-flags: --edition 2018 -// check-pass -#![feature(try_blocks)] -#![warn(unreachable_code)] - -fn err() -> Result { - Err(()) -} - -// In the following cases unreachable code is autogenerated and should not be reported. - -fn test_ok_wrapped_divergent_expr_1() { - let res: Result = try { - loop { - err()?; - } - }; - println!("res: {:?}", res); -} - -fn test_ok_wrapped_divergent_expr_2() { - let _: Result = try { - return - }; -} - -fn test_autogenerated_unit_after_divergent_expr() { - let _: Result<(), ()> = try { - return; - }; -} - -// In the following cases unreachable code should be reported. - -fn test_try_block_after_divergent_stmt() { - let _: Result = { - return; - - try { - loop { - err()?; - } - } - // ~^^^^^ WARNING unreachable expression - }; -} - -fn test_wrapped_divergent_expr() { - let _: Result = { - Err(return) - // ~^ WARNING unreachable call - }; -} - -fn test_expr_after_divergent_stmt_in_try_block() { - let res: Result = try { - loop { - err()?; - } - - 42 - // ~^ WARNING unreachable expression - }; - println!("res: {:?}", res); -} - -fn main() { - test_ok_wrapped_divergent_expr_1(); - test_ok_wrapped_divergent_expr_2(); - test_autogenerated_unit_after_divergent_expr(); - test_try_block_after_divergent_stmt(); - test_wrapped_divergent_expr(); - test_expr_after_divergent_stmt_in_try_block(); -} diff --git a/src/test/ui/try-block/try-block-unreachable-code-lint.stderr b/src/test/ui/try-block/try-block-unreachable-code-lint.stderr deleted file mode 100644 index 54fed04d400e9..0000000000000 --- a/src/test/ui/try-block/try-block-unreachable-code-lint.stderr +++ /dev/null @@ -1,38 +0,0 @@ -warning: unreachable expression - --> $DIR/try-block-unreachable-code-lint.rs:41:9 - | -LL | return; - | ------ any code following this expression is unreachable -LL | -LL | / try { -LL | | loop { -LL | | err()?; -LL | | } -LL | | } - | |_________^ unreachable expression - | -note: lint level defined here - --> $DIR/try-block-unreachable-code-lint.rs:6:9 - | -LL | #![warn(unreachable_code)] - | ^^^^^^^^^^^^^^^^ - -warning: unreachable call - --> $DIR/try-block-unreachable-code-lint.rs:52:9 - | -LL | Err(return) - | ^^^ ------ any code following this expression is unreachable - | | - | unreachable call - -warning: unreachable expression - --> $DIR/try-block-unreachable-code-lint.rs:63:9 - | -LL | / loop { -LL | | err()?; -LL | | } - | |_________- any code following this expression is unreachable -LL | -LL | 42 - | ^^ unreachable expression - diff --git a/src/test/ui/never_type/try_from.rs b/src/test/ui/try_from.rs similarity index 100% rename from src/test/ui/never_type/try_from.rs rename to src/test/ui/try_from.rs diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr index 357b33de51b84..128a85e15634c 100644 --- a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr +++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr @@ -6,4 +6,3 @@ LL | Self::A => (), error: aborting due to previous error -For more information about this error, try `rustc --explain E0533`. diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr index c6528e417d8ae..c1ea816b7facf 100644 --- a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr +++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr @@ -39,5 +39,5 @@ LL | let Alias::Unit() = panic!(); error: aborting due to 5 previous errors -Some errors have detailed explanations: E0164, E0533, E0618. +Some errors have detailed explanations: E0164, E0618. For more information about an error, try `rustc --explain E0164`. diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr index 63c07224353e2..dd90dd1b06fe2 100644 --- a/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr @@ -9,10 +9,8 @@ error[E0277]: the trait bound `T: Trait` is not satisfied | LL | type Underconstrained = impl 'static; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` -... -LL | fn underconstrain(_: T) -> Underconstrained { - | - help: consider restricting this bound: `T: Trait` | + = help: consider adding a `where T: Trait` bound = note: the return type of a function must have a statically known size error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr index ba892f6ed7c7b..574432bdcf6de 100644 --- a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr @@ -15,11 +15,9 @@ error[E0277]: `U` doesn't implement `std::fmt::Debug` | LL | type Underconstrained = impl 'static; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` -... -LL | fn underconstrained(_: U) -> Underconstrained { - | - help: consider restricting this bound: `U: std::fmt::Debug` | = help: the trait `std::fmt::Debug` is not implemented for `U` + = help: consider adding a `where U: std::fmt::Debug` bound = note: the return type of a function must have a statically known size error[E0277]: `V` doesn't implement `std::fmt::Debug` @@ -27,11 +25,9 @@ error[E0277]: `V` doesn't implement `std::fmt::Debug` | LL | type Underconstrained2 = impl 'static; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` -... -LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { - | - help: consider restricting this bound: `V: std::fmt::Debug` | = help: the trait `std::fmt::Debug` is not implemented for `V` + = help: consider adding a `where V: std::fmt::Debug` bound = note: the return type of a function must have a statically known size error: aborting due to 4 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs deleted file mode 100644 index 12eb75ae4c019..0000000000000 --- a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs +++ /dev/null @@ -1,17 +0,0 @@ -// check-pass - -#![feature(type_alias_impl_trait)] - -type T = impl Sized; -// The concrete type referred by impl-trait-type-alias(`T`) is guaranteed -// to be the same as where it occurs, whereas `impl Trait`'s instance is location sensitive; -// so difference assertion should not be declared on impl-trait-type-alias's instances. -// for details, check RFC-2515: -// https://github.com/rust-lang/rfcs/blob/master/text/2515-type_alias_impl_trait.md - -fn take(_: fn() -> T) {} - -fn main() { - take(|| {}); - take(|| {}); -} diff --git a/src/test/ui/type/type-ascription-with-fn-call.stderr b/src/test/ui/type/type-ascription-with-fn-call.stderr index eeaca5300f9b6..624c817e33e32 100644 --- a/src/test/ui/type/type-ascription-with-fn-call.stderr +++ b/src/test/ui/type/type-ascription-with-fn-call.stderr @@ -11,4 +11,3 @@ LL | f(); error: aborting due to previous error -For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index 6802bc38b89c9..742a709958fa0 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr @@ -52,10 +52,9 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | trait Super { } | -------------------- required by `Super` LL | trait Base: Super { } - | ^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | help: consider restricting this bound: `T: std::marker::Copy` - | 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 error[E0277]: cannot add `u8` to `i32` --> $DIR/type-check-defaults.rs:24:66 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 7ce249a60b85e..7d4bbc813c09c 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 @@ -4,10 +4,10 @@ error[E0277]: the trait bound `Self: Tr` is not satisfied LL | fn op(_: T) -> Self; | -------------------- required by `Tr::op` ... -LL | fn test(u: U) -> Self { - | - help: consider further restricting `Self`: `where Self: Tr` LL | Tr::op(u) | ^^^^^^ the trait `Tr` is not implemented for `Self` + | + = help: consider adding a `where Self: Tr` bound error[E0277]: the trait bound `Self: Tr` is not satisfied --> $DIR/type-params-in-different-spaces-2.rs:16:9 @@ -15,10 +15,10 @@ error[E0277]: the trait bound `Self: Tr` is not satisfied LL | fn op(_: T) -> Self; | -------------------- required by `Tr::op` ... -LL | fn test(u: U) -> Self { - | - help: consider further restricting `Self`: `where Self: Tr` LL | Tr::op(u) | ^^^^^^ the trait `Tr` is not implemented for `Self` + | + = help: consider adding a `where Self: Tr` bound error: aborting due to 2 previous errors diff --git a/src/test/ui/type/type-path-err-node-types.stderr b/src/test/ui/type/type-path-err-node-types.stderr index ea9cca2bfaab0..cd93525c76219 100644 --- a/src/test/ui/type/type-path-err-node-types.stderr +++ b/src/test/ui/type/type-path-err-node-types.stderr @@ -30,5 +30,5 @@ LL | let _ = |a, b: _| -> _ { 0 }; error: aborting due to 5 previous errors -Some errors have detailed explanations: E0282, E0412, E0425, E0433, E0576. +Some errors have detailed explanations: E0282, E0412, E0425, E0433. For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr index 8755bcded9d2f..1184e30749fe0 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr @@ -6,4 +6,3 @@ LL | auto trait Magic : Sized where Option : Magic {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0568`. diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr index 5a38883490959..7b45ca07b35c7 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr @@ -6,4 +6,3 @@ LL | auto trait Magic: Copy {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0568`. diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed deleted file mode 100644 index 7a108d880bed3..0000000000000 --- a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed +++ /dev/null @@ -1,17 +0,0 @@ -// run-rustfix -// Test that we do not consider associated types to be sendable without -// some applicable trait bound (and we don't ICE). -#![allow(dead_code)] - -trait Trait { - type AssocType; - fn dummy(&self) { } -} -fn bar() where ::AssocType: std::marker::Send { - is_send::(); //~ ERROR E0277 -} - -fn is_send() { -} - -fn main() { } diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.rs b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.rs index bafc1657737f4..d648353938674 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.rs @@ -1,7 +1,5 @@ -// run-rustfix // Test that we do not consider associated types to be sendable without // some applicable trait bound (and we don't ICE). -#![allow(dead_code)] trait Trait { type AssocType; 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 2e54cdf01320d..b842d0ae1a248 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 @@ -1,8 +1,6 @@ error[E0277]: `::AssocType` cannot be sent between threads safely - --> $DIR/typeck-default-trait-impl-assoc-type.rs:11:5 + --> $DIR/typeck-default-trait-impl-assoc-type.rs:9:5 | -LL | fn bar() { - | - help: consider further restricting the associated type: `where ::AssocType: std::marker::Send` LL | is_send::(); | ^^^^^^^^^^^^^^^^^^^^^^^ `::AssocType` cannot be sent between threads safely ... @@ -10,6 +8,7 @@ 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 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 a84aef5fdbdb6..b3139083b1ac8 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,8 +1,6 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/typeck-default-trait-impl-send-param.rs:5:15 | -LL | fn foo() { - | - help: consider restricting this bound: `T: std::marker::Send` LL | is_send::() | ^ `T` cannot be sent between threads safely ... @@ -10,6 +8,7 @@ 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 error: aborting due to previous error diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr index de3a997a19ed8..b2fe1b281fc99 100644 --- a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -38,7 +38,7 @@ note: the anonymous lifetime #1 defined on the method body at 37:5... | LL | fn dummy2(self: &Bar) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 35:6 +note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 35:6 --> $DIR/ufcs-explicit-self-bad.rs:35:6 | LL | impl<'a, T> SomeTrait for &'a Bar { @@ -52,7 +52,7 @@ LL | fn dummy2(self: &Bar) {} | = note: expected type `&'a Bar` found type `&Bar` -note: the lifetime `'a` as defined on the impl at 35:6... +note: the lifetime 'a as defined on the impl at 35:6... --> $DIR/ufcs-explicit-self-bad.rs:35:6 | LL | impl<'a, T> SomeTrait for &'a Bar { @@ -76,7 +76,7 @@ note: the anonymous lifetime #2 defined on the method body at 39:5... | LL | fn dummy3(self: &&Bar) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 35:6 +note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 35:6 --> $DIR/ufcs-explicit-self-bad.rs:35:6 | LL | impl<'a, T> SomeTrait for &'a Bar { @@ -90,7 +90,7 @@ LL | fn dummy3(self: &&Bar) {} | = note: expected type `&'a Bar` found type `&Bar` -note: the lifetime `'a` as defined on the impl at 35:6... +note: the lifetime 'a as defined on the impl at 35:6... --> $DIR/ufcs-explicit-self-bad.rs:35:6 | LL | impl<'a, T> SomeTrait for &'a Bar { diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr index dee990ec3d1cb..5ee8adaaf270f 100644 --- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr +++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr @@ -200,5 +200,5 @@ LL | ::X::N; error: aborting due to 32 previous errors -Some errors have detailed explanations: E0223, E0433, E0575, E0576, E0599. +Some errors have detailed explanations: E0223, E0433, E0599. For more information about an error, try `rustc --explain E0223`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.polonius.stderr b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.polonius.stderr new file mode 100644 index 0000000000000..4b906f75149af --- /dev/null +++ b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.polonius.stderr @@ -0,0 +1,60 @@ +error[E0597]: `factorial` does not live long enough + --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:15:17 + | +LL | let f = |x: u32| -> u32 { + | --------------- value captured here +LL | let g = factorial.as_ref().unwrap(); + | ^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `factorial` dropped here while still borrowed + | borrow might be used here, when `factorial` is dropped and runs the destructor for type `std::option::Option u32>>` + +error[E0506]: cannot assign to `factorial` because it is borrowed + --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:20:5 + | +LL | let f = |x: u32| -> u32 { + | --------------- borrow of `factorial` occurs here +LL | let g = factorial.as_ref().unwrap(); + | --------- borrow occurs due to use in closure +... +LL | factorial = Some(Box::new(f)); + | ^^^^^^^^^ + | | + | assignment to borrowed `factorial` occurs here + | borrow later used here + +error[E0597]: `factorial` does not live long enough + --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:28:17 + | +LL | let f = |x: u32| -> u32 { + | --------------- value captured here +LL | let g = factorial.as_ref().unwrap(); + | ^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `factorial` dropped here while still borrowed + | borrow might be used here, when `factorial` is dropped and runs the destructor for type `std::option::Option u32>>` + +error[E0506]: cannot assign to `factorial` because it is borrowed + --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:33:5 + | +LL | let f = |x: u32| -> u32 { + | --------------- borrow of `factorial` occurs here +LL | let g = factorial.as_ref().unwrap(); + | --------- borrow occurs due to use in closure +... +LL | factorial = Some(Box::new(f)); + | ^^^^^^^^^ + | | + | assignment to borrowed `factorial` occurs here + | borrow later used here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0506, E0597. +For more information about an error, try `rustc --explain E0506`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs b/src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs index 5d1e00d2d3535..f86499e2e3f86 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs @@ -10,7 +10,6 @@ // This is a regression test for issue #17021. // // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet use std::ptr; diff --git a/src/test/ui/underscore-imports/hygiene-2.rs b/src/test/ui/underscore-imports/hygiene-2.rs deleted file mode 100644 index bea61eae6b51a..0000000000000 --- a/src/test/ui/underscore-imports/hygiene-2.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Make sure that underscore imports with different contexts can exist in the -// same scope. - -// check-pass - -#![feature(decl_macro)] - -mod x { - pub use std::ops::Deref as _; -} - -macro n() { - pub use crate::x::*; -} - -#[macro_export] -macro_rules! p { - () => { pub use crate::x::*; } -} - -macro m($y:ident) { - mod $y { - crate::n!(); // Reexport of `Deref` should not be imported in `main` - crate::p!(); // Reexport of `Deref` should be imported into `main` - } -} - -m!(y); - -fn main() { - use crate::y::*; - (&()).deref(); -} diff --git a/src/test/ui/underscore-imports/hygiene.rs b/src/test/ui/underscore-imports/hygiene.rs deleted file mode 100644 index a254f6eaa5980..0000000000000 --- a/src/test/ui/underscore-imports/hygiene.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Make sure that underscore imports have the same hygiene considerations as -// other imports. - -#![feature(decl_macro)] - -mod x { - pub use std::ops::Deref as _; -} - - -macro glob_import() { - pub use crate::x::*; -} - -macro underscore_import() { - use std::ops::DerefMut as _; -} - -mod y { - crate::glob_import!(); - crate::underscore_import!(); -} - -macro create_module($y:ident) { - mod $y { - crate::glob_import!(); - crate::underscore_import!(); - } -} - -create_module!(z); - -fn main() { - use crate::y::*; - use crate::z::*; - glob_import!(); - underscore_import!(); - (&()).deref(); //~ ERROR no method named `deref` - (&mut ()).deref_mut(); //~ ERROR no method named `deref_mut` -} diff --git a/src/test/ui/underscore-imports/hygiene.stderr b/src/test/ui/underscore-imports/hygiene.stderr deleted file mode 100644 index 44cfc5cc5d22e..0000000000000 --- a/src/test/ui/underscore-imports/hygiene.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0599]: no method named `deref` found for type `&()` in the current scope - --> $DIR/hygiene.rs:38:11 - | -LL | (&()).deref(); - | ^^^^^ 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: - | -LL | use std::ops::Deref; - | - -error[E0599]: no method named `deref_mut` found for type `&mut ()` in the current scope - --> $DIR/hygiene.rs:39:15 - | -LL | (&mut ()).deref_mut(); - | ^^^^^^^^^ method not found in `&mut ()` - | - = 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: - | -LL | use std::ops::DerefMut; - | - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/underscore-imports/macro-expanded.rs b/src/test/ui/underscore-imports/macro-expanded.rs deleted file mode 100644 index 43f527bc9a408..0000000000000 --- a/src/test/ui/underscore-imports/macro-expanded.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Check that macro expanded underscore imports behave as expected - -// check-pass - -#![feature(decl_macro, rustc_attrs)] - -mod x { - pub use std::ops::Not as _; -} - -macro m() { - mod w { - mod y { - pub use std::ops::Deref as _; - } - use crate::x::*; - use self::y::*; - use std::ops::DerefMut as _; - fn f() { - false.not(); - (&()).deref(); - (&mut ()).deref_mut(); - } - } -} - -#[rustc_macro_transparency = "transparent"] -macro n() { - mod z { - pub use std::ops::Deref as _; - } - use crate::x::*; - use crate::z::*; - use std::ops::DerefMut as _; - fn f() { - false.not(); - (&()).deref(); - (&mut ()).deref_mut(); - } -} - -m!(); -n!(); - -fn main() {} diff --git a/src/test/ui/underscore-imports/shadow.stderr b/src/test/ui/underscore-imports/shadow.stderr index 102c17f6f5618..63262d0dc326d 100644 --- a/src/test/ui/underscore-imports/shadow.stderr +++ b/src/test/ui/underscore-imports/shadow.stderr @@ -5,7 +5,7 @@ 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: + = 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 diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index d0475bf08c38d..92e5ac282e4d6 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -24,4 +24,3 @@ LL | Box::new(items.iter()) error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr index 26e1be34ea75d..29ff1dc376089 100644 --- a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr +++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr @@ -12,13 +12,6 @@ LL | | } ... LL | let Foo::D(_y) = x; | ^^^^^^^^^^ pattern `A(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let Foo::D(_y) = x { /* */ } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr index a49344e45cec6..25519ab2d6a7d 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr @@ -51,13 +51,6 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered | LL | let Ok(x) = x; | ^^^^^ pattern `Err(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let Ok(x) = x { /* */ } - | error: aborting due to 7 previous errors diff --git a/src/test/ui/union/issue-41073.rs b/src/test/ui/union/issue-41073.rs deleted file mode 100644 index 91e9a0d0b659c..0000000000000 --- a/src/test/ui/union/issue-41073.rs +++ /dev/null @@ -1,24 +0,0 @@ -#![feature(untagged_unions)] - -union Test { - a: A, //~ ERROR unions may not contain fields that need dropping - b: B -} - -#[derive(Debug)] -struct A(i32); -impl Drop for A { - fn drop(&mut self) { println!("A"); } -} - -#[derive(Debug)] -struct B(f32); -impl Drop for B { - fn drop(&mut self) { println!("B"); } -} - -fn main() { - let mut test = Test { a: A(3) }; - println!("{:?}", unsafe { test.b }); - unsafe { test.b = B(0.5); } -} diff --git a/src/test/ui/union/issue-41073.stderr b/src/test/ui/union/issue-41073.stderr deleted file mode 100644 index 2e9598b227124..0000000000000 --- a/src/test/ui/union/issue-41073.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0740]: unions may not contain fields that need dropping - --> $DIR/issue-41073.rs:4:5 - | -LL | a: A, - | ^^^^ - | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/issue-41073.rs:4:5 - | -LL | a: A, - | ^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0740`. diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.rs b/src/test/ui/union/union-borrow-move-parent-sibling.rs index edf08e6ca678f..1b6052f10ba4a 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.rs +++ b/src/test/ui/union/union-borrow-move-parent-sibling.rs @@ -1,90 +1,51 @@ #![feature(untagged_unions)] #![allow(unused)] -use std::ops::{Deref, DerefMut}; - -#[derive(Default)] -struct MockBox { - value: [T; 1], -} - -impl MockBox { - fn new(value: T) -> Self { MockBox { value: [value] } } -} - -impl Deref for MockBox { - type Target = T; - fn deref(&self) -> &T { &self.value[0] } -} - -impl DerefMut for MockBox { - fn deref_mut(&mut self) -> &mut T { &mut self.value[0] } -} - -#[derive(Default)] -struct MockVec { - value: [T; 0], -} - -impl MockVec { - fn new() -> Self { MockVec { value: [] } } -} - -impl Deref for MockVec { - type Target = [T]; - fn deref(&self) -> &[T] { &self.value } -} - -impl DerefMut for MockVec { - fn deref_mut(&mut self) -> &mut [T] { &mut self.value } -} - - +#[allow(unions_with_drop_fields)] union U { - x: ((MockVec, MockVec), MockVec), - y: MockBox>, + x: ((Vec, Vec), Vec), + y: Box>, } fn use_borrow(_: &T) {} unsafe fn parent_sibling_borrow() { - let mut u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; + let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; let a = &mut u.x.0; let b = &u.y; //~ ERROR cannot borrow `u` (via `u.y`) use_borrow(a); } unsafe fn parent_sibling_move() { - let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; + let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; let a = u.x.0; let b = u.y; //~ ERROR use of moved value: `u` } unsafe fn grandparent_sibling_borrow() { - let mut u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; + let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; let a = &mut (u.x.0).0; let b = &u.y; //~ ERROR cannot borrow `u` (via `u.y`) use_borrow(a); } unsafe fn grandparent_sibling_move() { - let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; + let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; let a = (u.x.0).0; let b = u.y; //~ ERROR use of moved value: `u` } unsafe fn deref_sibling_borrow() { - let mut u = U { y: MockBox::default() }; + let mut u = U { y: Box::default() }; let a = &mut *u.y; let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`) use_borrow(a); } unsafe fn deref_sibling_move() { - let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; - // No way to test deref-move without Box in union - // let a = *u.y; - // let b = u.x; ERROR use of moved value: `u` + let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + let a = *u.y; + let b = u.x; //~ ERROR use of moved value: `u` } diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.stderr index 8ba155bafb0b9..2f4c921ea08f9 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.stderr +++ b/src/test/ui/union/union-borrow-move-parent-sibling.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`) - --> $DIR/union-borrow-move-parent-sibling.rs:53:13 + --> $DIR/union-borrow-move-parent-sibling.rs:15:13 | LL | let a = &mut u.x.0; | ---------- mutable borrow occurs here (via `u.x.0`) @@ -11,9 +11,9 @@ LL | use_borrow(a); = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0` error[E0382]: use of moved value: `u` - --> $DIR/union-borrow-move-parent-sibling.rs:60:13 + --> $DIR/union-borrow-move-parent-sibling.rs:22:13 | -LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; +LL | let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; | - move occurs because `u` has type `U`, which does not implement the `Copy` trait LL | let a = u.x.0; | ----- value moved here @@ -21,7 +21,7 @@ LL | let b = u.y; | ^^^ value used here after move error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`) - --> $DIR/union-borrow-move-parent-sibling.rs:66:13 + --> $DIR/union-borrow-move-parent-sibling.rs:28:13 | LL | let a = &mut (u.x.0).0; | -------------- mutable borrow occurs here (via `u.x.0.0`) @@ -33,28 +33,38 @@ LL | use_borrow(a); = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0` error[E0382]: use of moved value: `u` - --> $DIR/union-borrow-move-parent-sibling.rs:73:13 + --> $DIR/union-borrow-move-parent-sibling.rs:35:13 | -LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; +LL | let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; | - move occurs because `u` has type `U`, which does not implement the `Copy` trait LL | let a = (u.x.0).0; | --------- value moved here LL | let b = u.y; | ^^^ value used here after move -error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`) - --> $DIR/union-borrow-move-parent-sibling.rs:79:13 +error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `*u.y`) + --> $DIR/union-borrow-move-parent-sibling.rs:41:13 | LL | let a = &mut *u.y; - | --- mutable borrow occurs here (via `u.y`) + | --------- mutable borrow occurs here (via `*u.y`) LL | let b = &u.x; - | ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here + | ^^^^ immutable borrow of `u.x` -- which overlaps with `*u.y` -- occurs here LL | use_borrow(a); | - mutable borrow later used here | - = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y` + = note: `u.x` is a field of the union `U`, so it overlaps the field `*u.y` -error: aborting due to 5 previous errors +error[E0382]: use of moved value: `u` + --> $DIR/union-borrow-move-parent-sibling.rs:48:13 + | +LL | let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + | - move occurs because `u` has type `U`, which does not implement the `Copy` trait +LL | let a = *u.y; + | ---- value moved here +LL | let b = u.x; + | ^^^ value used here after move + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0382, E0502. For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/union/union-custom-drop.rs b/src/test/ui/union/union-custom-drop.rs deleted file mode 100644 index 8f816cc1b737c..0000000000000 --- a/src/test/ui/union/union-custom-drop.rs +++ /dev/null @@ -1,19 +0,0 @@ -// test for a union with a field that's a union with a manual impl Drop -// Ensures we do not treat all unions as not having any drop glue. - -#![feature(untagged_unions)] - -union Foo { - bar: Bar, //~ ERROR unions may not contain fields that need dropping -} - -union Bar { - a: i32, - b: u32, -} - -impl Drop for Bar { - fn drop(&mut self) {} -} - -fn main() {} diff --git a/src/test/ui/union/union-custom-drop.stderr b/src/test/ui/union/union-custom-drop.stderr deleted file mode 100644 index ee2333f905fb4..0000000000000 --- a/src/test/ui/union/union-custom-drop.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0740]: unions may not contain fields that need dropping - --> $DIR/union-custom-drop.rs:7:5 - | -LL | bar: Bar, - | ^^^^^^^^ - | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-custom-drop.rs:7:5 - | -LL | bar: Bar, - | ^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0740`. diff --git a/src/test/ui/union/union-derive-clone.rs b/src/test/ui/union/union-derive-clone.rs index 60e280f53f52c..64c3caef44906 100644 --- a/src/test/ui/union/union-derive-clone.rs +++ b/src/test/ui/union/union-derive-clone.rs @@ -1,7 +1,5 @@ #![feature(untagged_unions)] -use std::mem::ManuallyDrop; - #[derive(Clone)] //~ ERROR the trait bound `U1: std::marker::Copy` is not satisfied union U1 { a: u8, @@ -20,19 +18,14 @@ union U3 { } #[derive(Clone, Copy)] -union U4 { +union U4 { a: T, // OK } -#[derive(Clone, Copy)] -union U5 { - a: ManuallyDrop, // OK -} - #[derive(Clone)] struct CloneNoCopy; fn main() { - let u = U5 { a: ManuallyDrop::new(CloneNoCopy) }; - let w = u.clone(); //~ ERROR no method named `clone` found for type `U5` + let u = U4 { a: CloneNoCopy }; + let w = u.clone(); //~ ERROR no method named `clone` found for type `U4` } diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index 6893f9176f2db..4f4c779b12bb3 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -1,22 +1,22 @@ error[E0277]: the trait bound `U1: std::marker::Copy` is not satisfied - --> $DIR/union-derive-clone.rs:5:10 + --> $DIR/union-derive-clone.rs:3:10 | LL | #[derive(Clone)] | ^^^^^ the trait `std::marker::Copy` is not implemented for `U1` | = note: required by `std::clone::AssertParamIsCopy` -error[E0599]: no method named `clone` found for type `U5` in the current scope - --> $DIR/union-derive-clone.rs:37:15 +error[E0599]: no method named `clone` found for type `U4` in the current scope + --> $DIR/union-derive-clone.rs:30:15 | -LL | union U5 { +LL | union U4 { | ----------- method `clone` not found for this ... LL | let w = u.clone(); - | ^^^^^ method not found in `U5` + | ^^^^^ method not found in `U4` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `U5 : std::clone::Clone` + `U4 : std::clone::Clone` = 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: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/union/union-derive-rpass.rs b/src/test/ui/union/union-derive-rpass.rs index b2f7ae679fd68..d4b82cdb250b1 100644 --- a/src/test/ui/union/union-derive-rpass.rs +++ b/src/test/ui/union/union-derive-rpass.rs @@ -1,6 +1,7 @@ // run-pass #![allow(dead_code)] #![allow(unused_variables)] +#![allow(unions_with_drop_fields)] // Some traits can be derived for unions. @@ -23,11 +24,11 @@ impl PartialEq for U { fn eq(&self, rhs: &Self) -> bool { true } } Copy, Eq )] -union W { +union W { a: T, } -impl PartialEq for W { fn eq(&self, rhs: &Self) -> bool { true } } +impl PartialEq for W { fn eq(&self, rhs: &Self) -> bool { true } } fn main() { let u = U { b: 0 }; diff --git a/src/test/ui/union/union-drop-assign.rs b/src/test/ui/union/union-drop-assign.rs index f1511b0a60180..c4349c454641b 100644 --- a/src/test/ui/union/union-drop-assign.rs +++ b/src/test/ui/union/union-drop-assign.rs @@ -1,16 +1,15 @@ // run-pass #![allow(unused_assignments)] +#![allow(unions_with_drop_fields)] // Drop works for union itself. #![feature(untagged_unions)] -use std::mem::ManuallyDrop; - struct S; union U { - a: ManuallyDrop + a: S } impl Drop for S { @@ -29,11 +28,11 @@ static mut CHECK: u8 = 0; fn main() { unsafe { - let mut u = U { a: ManuallyDrop::new(S) }; + let mut u = U { a: S }; assert_eq!(CHECK, 0); - u = U { a: ManuallyDrop::new(S) }; + u = U { a: S }; assert_eq!(CHECK, 1); // union itself is assigned, union is dropped, field is not dropped - *u.a = S; + u.a = S; assert_eq!(CHECK, 11); // union field is assigned, field is dropped } } diff --git a/src/test/ui/union/union-drop.rs b/src/test/ui/union/union-drop.rs index daa03ce6b6fd8..2060950dda951 100644 --- a/src/test/ui/union/union-drop.rs +++ b/src/test/ui/union/union-drop.rs @@ -1,6 +1,7 @@ // run-pass #![allow(dead_code)] #![allow(unused_variables)] +#![allow(unions_with_drop_fields)] // Drop works for union itself. @@ -20,6 +21,12 @@ union Y { a: S, } +impl Drop for S { + fn drop(&mut self) { + unsafe { CHECK += 10; } + } +} + impl Drop for U { fn drop(&mut self) { unsafe { CHECK += 1; } @@ -44,10 +51,10 @@ fn main() { { let w = W { a: S }; } - assert_eq!(CHECK, 2); // 2, dtor of W is called + assert_eq!(CHECK, 2); // 2, not 11, dtor of S is not called { let y = Y { a: S }; } - assert_eq!(CHECK, 2); // 2, dtor of Y is called + assert_eq!(CHECK, 2); // 2, not 12, dtor of S is not called } } diff --git a/src/test/ui/union/union-generic-rpass.rs b/src/test/ui/union/union-generic-rpass.rs index eb169c516d2a8..6f2caf8dc5b1e 100644 --- a/src/test/ui/union/union-generic-rpass.rs +++ b/src/test/ui/union/union-generic-rpass.rs @@ -1,33 +1,37 @@ // run-pass #![allow(dead_code)] +#![allow(unions_with_drop_fields)] #![feature(untagged_unions)] -use std::mem::ManuallyDrop; - union MaybeItem { - elem: ManuallyDrop, + elem: T::Item, none: (), } -union U where A: Copy, B: Copy { +union U { a: A, b: B, } -unsafe fn union_transmute(a: A) -> B where A: Copy, B: Copy { +unsafe fn union_transmute(a: A) -> B { U { a: a }.b } fn main() { unsafe { + let u = U::> { a: String::from("abcd") }; + + assert_eq!(u.b.len(), 4); + assert_eq!(u.b[0], b'a'); + let b = union_transmute::<(u8, u8), u16>((1, 1)); assert_eq!(b, (1 << 8) + 1); let v: Vec = vec![1, 2, 3]; let mut i = v.iter(); i.next(); - let mi = MaybeItem::> { elem: ManuallyDrop::new(i.next().unwrap()) }; - assert_eq!(**mi.elem, 2); + let mi = MaybeItem::> { elem: i.next().unwrap() }; + assert_eq!(*mi.elem, 2); } } diff --git a/src/test/ui/union/union-manuallydrop-rpass.rs b/src/test/ui/union/union-manuallydrop-rpass.rs deleted file mode 100644 index a43a505086569..0000000000000 --- a/src/test/ui/union/union-manuallydrop-rpass.rs +++ /dev/null @@ -1,42 +0,0 @@ -#![feature(untagged_unions)] -#![allow(dead_code)] -// run-pass - -use std::mem::needs_drop; -use std::mem::ManuallyDrop; - -struct NeedDrop; - -impl Drop for NeedDrop { - fn drop(&mut self) {} -} - -union UnionOk1 { - empty: (), - value: ManuallyDrop, -} - -union UnionOk2 { - value: ManuallyDrop, -} - -#[allow(dead_code)] -union UnionOk3 { - empty: (), - value: T, -} - -trait Foo { } - -trait ImpliesCopy : Copy { } - -#[allow(dead_code)] -union UnionOk4 { - value: T, -} - -fn main() { - // NeedDrop should not make needs_drop true - assert!(!needs_drop::>()); - assert!(!needs_drop::>()); -} diff --git a/src/test/ui/union/union-nodrop.rs b/src/test/ui/union/union-nodrop.rs index 59282bec59b84..4cd64ddb5d67f 100644 --- a/src/test/ui/union/union-nodrop.rs +++ b/src/test/ui/union/union-nodrop.rs @@ -1,11 +1,12 @@ // run-pass +#![feature(core_intrinsics)] #![feature(untagged_unions)] +#![allow(unions_with_drop_fields)] #![allow(dead_code)] -use std::mem::needs_drop; -use std::mem::ManuallyDrop; +use std::intrinsics::needs_drop; struct NeedDrop; @@ -15,14 +16,10 @@ impl Drop for NeedDrop { // Constant expressios allow `NoDrop` to go out of scope, // unlike a value of the interior type implementing `Drop`. -static X: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1; - -const Y: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1; - -const fn _f() { (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1 } +static X: () = (NoDrop { inner: NeedDrop }, ()).1; // A union that scrubs the drop glue from its inner type -union NoDrop { inner: ManuallyDrop } +union NoDrop {inner: T} // Copy currently can't be implemented on drop-containing unions, // this may change later @@ -43,7 +40,7 @@ struct Baz { y: Box, } -union ActuallyDrop { inner: ManuallyDrop } +union ActuallyDrop {inner: T} impl Drop for ActuallyDrop { fn drop(&mut self) {} diff --git a/src/test/ui/union/union-overwrite.rs b/src/test/ui/union/union-overwrite.rs index 8234beb74a826..64c60604ba9f0 100644 --- a/src/test/ui/union/union-overwrite.rs +++ b/src/test/ui/union/union-overwrite.rs @@ -1,27 +1,21 @@ // run-pass +#![allow(unions_with_drop_fields)] + #![feature(untagged_unions)] #[repr(C)] -#[derive(Copy, Clone)] struct Pair(T, U); #[repr(C)] -#[derive(Copy, Clone)] struct Triple(T, T, T); #[repr(C)] -union U -where - A: Copy, B: Copy -{ +union U { a: Pair, b: B, } #[repr(C)] -union W -where - A: Copy, B: Copy -{ +union W { a: A, b: B, } diff --git a/src/test/ui/union/union-sized-field.stderr b/src/test/ui/union/union-sized-field.stderr index c9fec1d21d152..8914003068385 100644 --- a/src/test/ui/union/union-sized-field.stderr +++ b/src/test/ui/union/union-sized-field.stderr @@ -1,37 +1,34 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/union-sized-field.rs:4:5 | -LL | union Foo { - | -- help: consider further restricting this bound: `T: std::marker::Sized +` LL | value: T, | ^^^^^^^^ 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: no field of a union may have a dynamically sized type error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/union-sized-field.rs:9:5 | -LL | struct Foo2 { - | -- help: consider further restricting this bound: `T: std::marker::Sized +` LL | value: T, | ^^^^^^^^ 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: only the last field of a struct may have a dynamically sized type error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/union-sized-field.rs:15:11 | -LL | enum Foo3 { - | -- help: consider further restricting this bound: `T: std::marker::Sized +` LL | Value(T), | ^ 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: no field of an enum variant may have a dynamically sized type error: aborting due to 3 previous errors diff --git a/src/test/ui/union/union-unsafe.rs b/src/test/ui/union/union-unsafe.rs index 8535cbd019ce8..6cfde35fe4c34 100644 --- a/src/test/ui/union/union-unsafe.rs +++ b/src/test/ui/union/union-unsafe.rs @@ -1,16 +1,15 @@ #![feature(untagged_unions)] -use std::mem::ManuallyDrop; union U1 { a: u8 } union U2 { - a: ManuallyDrop + a: String } union U3 { - a: ManuallyDrop + a: T } union U4 { @@ -18,16 +17,13 @@ union U4 { } fn generic_noncopy() { - let mut u3 = U3 { a: ManuallyDrop::new(T::default()) }; - u3.a = ManuallyDrop::new(T::default()); //~ ERROR assignment to non-`Copy` union field is unsafe - *u3.a = T::default(); //~ ERROR access to union field is unsafe + let mut u3 = U3 { a: T::default() }; + u3.a = T::default(); //~ ERROR assignment to non-`Copy` union field is unsafe } fn generic_copy() { - let mut u3 = U3 { a: ManuallyDrop::new(T::default()) }; - u3.a = ManuallyDrop::new(T::default()); // OK - *u3.a = T::default(); //~ ERROR access to union field is unsafe - + let mut u3 = U3 { a: T::default() }; + u3.a = T::default(); // OK let mut u4 = U4 { a: T::default() }; u4.a = T::default(); // OK } @@ -36,20 +32,14 @@ fn main() { let mut u1 = U1 { a: 10 }; // OK let a = u1.a; //~ ERROR access to union field is unsafe u1.a = 11; // OK - let U1 { a } = u1; //~ ERROR access to union field is unsafe if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe // let U1 { .. } = u1; // OK - let mut u2 = U2 { a: ManuallyDrop::new(String::from("old")) }; // OK - u2.a = ManuallyDrop::new(String::from("new")); //~ ERROR assignment to non-`Copy` union - *u2.a = String::from("new"); //~ ERROR access to union field is unsafe - - let mut u3 = U3 { a: ManuallyDrop::new(0) }; // OK - u3.a = ManuallyDrop::new(1); // OK - *u3.a = 1; //~ ERROR access to union field is unsafe - - let mut u3 = U3 { a: ManuallyDrop::new(String::from("old")) }; // OK - u3.a = ManuallyDrop::new(String::from("new")); //~ ERROR assignment to non-`Copy` union - *u3.a = String::from("new"); //~ ERROR access to union field is unsafe + let mut u2 = U2 { a: String::from("old") }; // OK + u2.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field is unsafe + let mut u3 = U3 { a: 0 }; // OK + u3.a = 1; // OK + let mut u3 = U3 { a: String::from("old") }; // OK + u3.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field is unsafe } diff --git a/src/test/ui/union/union-unsafe.stderr b/src/test/ui/union/union-unsafe.stderr index e020dab63f8f4..ab62508fcf666 100644 --- a/src/test/ui/union/union-unsafe.stderr +++ b/src/test/ui/union/union-unsafe.stderr @@ -1,29 +1,13 @@ error[E0133]: assignment to non-`Copy` union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:22:5 + --> $DIR/union-unsafe.rs:21:5 | -LL | u3.a = ManuallyDrop::new(T::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to non-`Copy` union field +LL | u3.a = T::default(); + | ^^^^ assignment to non-`Copy` union field | = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:23:6 - | -LL | *u3.a = T::default(); - | ^^^^ access to union field - | - = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior - -error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:29:6 - | -LL | *u3.a = T::default(); - | ^^^^ access to union field - | - = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior - -error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:37:13 + --> $DIR/union-unsafe.rs:33:13 | LL | let a = u1.a; | ^^^^ access to union field @@ -31,7 +15,7 @@ LL | let a = u1.a; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:40:14 + --> $DIR/union-unsafe.rs:35:14 | LL | let U1 { a } = u1; | ^ access to union field @@ -39,7 +23,7 @@ LL | let U1 { a } = u1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:41:20 + --> $DIR/union-unsafe.rs:36:20 | LL | if let U1 { a: 12 } = u1 {} | ^^ access to union field @@ -47,45 +31,21 @@ LL | if let U1 { a: 12 } = u1 {} = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: assignment to non-`Copy` union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:45:5 + --> $DIR/union-unsafe.rs:40:5 | -LL | u2.a = ManuallyDrop::new(String::from("new")); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to non-`Copy` union field +LL | u2.a = String::from("new"); + | ^^^^ assignment to non-`Copy` union field | = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized -error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:46:6 - | -LL | *u2.a = String::from("new"); - | ^^^^ access to union field - | - = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior - -error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:50:6 - | -LL | *u3.a = 1; - | ^^^^ access to union field - | - = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior - error[E0133]: assignment to non-`Copy` union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:53:5 + --> $DIR/union-unsafe.rs:44:5 | -LL | u3.a = ManuallyDrop::new(String::from("new")); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to non-`Copy` union field +LL | u3.a = String::from("new"); + | ^^^^ assignment to non-`Copy` union field | = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized -error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:54:6 - | -LL | *u3.a = String::from("new"); - | ^^^^ access to union field - | - = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior - -error: aborting due to 11 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/union/union-with-drop-fields-lint-rpass.rs b/src/test/ui/union/union-with-drop-fields-lint-rpass.rs new file mode 100644 index 0000000000000..4dbeb7c1e7e97 --- /dev/null +++ b/src/test/ui/union/union-with-drop-fields-lint-rpass.rs @@ -0,0 +1,32 @@ +// run-pass + +#![feature(untagged_unions)] +#![allow(dead_code)] +#![allow(unions_with_drop_fields)] + +union U { + a: u8, // OK +} + +union W { + a: String, // OK + b: String, // OK +} + +struct S(String); + +// `S` doesn't implement `Drop` trait, but still has non-trivial destructor +union Y { + a: S, // OK +} + +// We don't know if `T` is trivially-destructable or not until trans +union J { + a: T, // OK +} + +union H { + a: T, // OK +} + +fn main() {} diff --git a/src/test/ui/union/union-with-drop-fields.rs b/src/test/ui/union/union-with-drop-fields-lint.rs similarity index 60% rename from src/test/ui/union/union-with-drop-fields.rs rename to src/test/ui/union/union-with-drop-fields-lint.rs index e3c63a6d5b5a2..8e502aa55f952 100644 --- a/src/test/ui/union/union-with-drop-fields.rs +++ b/src/test/ui/union/union-with-drop-fields-lint.rs @@ -1,12 +1,13 @@ #![feature(untagged_unions)] #![allow(dead_code)] +#![deny(unions_with_drop_fields)] union U { a: u8, // OK } union W { - a: String, //~ ERROR unions may not contain fields that need dropping + a: String, //~ ERROR union contains a field with possibly non-trivial drop code b: String, // OK, only one field is reported } @@ -14,12 +15,12 @@ struct S(String); // `S` doesn't implement `Drop` trait, but still has non-trivial destructor union Y { - a: S, //~ ERROR unions may not contain fields that need dropping + a: S, //~ ERROR union contains a field with possibly non-trivial drop code } // We don't know if `T` is trivially-destructable or not until trans union J { - a: T, //~ ERROR unions may not contain fields that need dropping + a: T, //~ ERROR union contains a field with possibly non-trivial drop code } union H { diff --git a/src/test/ui/union/union-with-drop-fields-lint.stderr b/src/test/ui/union/union-with-drop-fields-lint.stderr new file mode 100644 index 0000000000000..2f90f240d2e19 --- /dev/null +++ b/src/test/ui/union/union-with-drop-fields-lint.stderr @@ -0,0 +1,26 @@ +error: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union + --> $DIR/union-with-drop-fields-lint.rs:10:5 + | +LL | a: String, + | ^^^^^^^^^ + | +note: lint level defined here + --> $DIR/union-with-drop-fields-lint.rs:3:9 + | +LL | #![deny(unions_with_drop_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union + --> $DIR/union-with-drop-fields-lint.rs:18:5 + | +LL | a: S, + | ^^^^ + +error: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union + --> $DIR/union-with-drop-fields-lint.rs:23:5 + | +LL | a: T, + | ^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/union/union-with-drop-fields.stderr b/src/test/ui/union/union-with-drop-fields.stderr deleted file mode 100644 index 0e77279be616a..0000000000000 --- a/src/test/ui/union/union-with-drop-fields.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0740]: unions may not contain fields that need dropping - --> $DIR/union-with-drop-fields.rs:9:5 - | -LL | a: String, - | ^^^^^^^^^ - | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:9:5 - | -LL | a: String, - | ^^^^^^^^^ - -error[E0740]: unions may not contain fields that need dropping - --> $DIR/union-with-drop-fields.rs:17:5 - | -LL | a: S, - | ^^^^ - | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:17:5 - | -LL | a: S, - | ^^^^ - -error[E0740]: unions may not contain fields that need dropping - --> $DIR/union-with-drop-fields.rs:22:5 - | -LL | a: T, - | ^^^^ - | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:22:5 - | -LL | a: T, - | ^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0740`. diff --git a/src/test/ui/reachable/auxiliary/unreachable_variant.rs b/src/test/ui/unreachable/auxiliary/unreachable_variant.rs similarity index 100% rename from src/test/ui/reachable/auxiliary/unreachable_variant.rs rename to src/test/ui/unreachable/auxiliary/unreachable_variant.rs diff --git a/src/test/ui/reachable/unreachable-arm.rs b/src/test/ui/unreachable/unreachable-arm.rs similarity index 100% rename from src/test/ui/reachable/unreachable-arm.rs rename to src/test/ui/unreachable/unreachable-arm.rs diff --git a/src/test/ui/reachable/unreachable-arm.stderr b/src/test/ui/unreachable/unreachable-arm.stderr similarity index 100% rename from src/test/ui/reachable/unreachable-arm.stderr rename to src/test/ui/unreachable/unreachable-arm.stderr diff --git a/src/test/ui/reachable/unreachable-code.rs b/src/test/ui/unreachable/unreachable-code.rs similarity index 100% rename from src/test/ui/reachable/unreachable-code.rs rename to src/test/ui/unreachable/unreachable-code.rs diff --git a/src/test/ui/reachable/unreachable-code.stderr b/src/test/ui/unreachable/unreachable-code.stderr similarity index 100% rename from src/test/ui/reachable/unreachable-code.stderr rename to src/test/ui/unreachable/unreachable-code.stderr diff --git a/src/test/ui/reachable/unreachable-in-call.rs b/src/test/ui/unreachable/unreachable-in-call.rs similarity index 100% rename from src/test/ui/reachable/unreachable-in-call.rs rename to src/test/ui/unreachable/unreachable-in-call.rs diff --git a/src/test/ui/reachable/unreachable-in-call.stderr b/src/test/ui/unreachable/unreachable-in-call.stderr similarity index 100% rename from src/test/ui/reachable/unreachable-in-call.stderr rename to src/test/ui/unreachable/unreachable-in-call.stderr diff --git a/src/test/ui/reachable/unreachable-loop-patterns.rs b/src/test/ui/unreachable/unreachable-loop-patterns.rs similarity index 95% rename from src/test/ui/reachable/unreachable-loop-patterns.rs rename to src/test/ui/unreachable/unreachable-loop-patterns.rs index 6f1d2efa1b200..56ab1a270a75d 100644 --- a/src/test/ui/reachable/unreachable-loop-patterns.rs +++ b/src/test/ui/unreachable/unreachable-loop-patterns.rs @@ -1,3 +1,5 @@ +// compile-fail + #![feature(never_type)] #![feature(exhaustive_patterns)] diff --git a/src/test/ui/reachable/unreachable-loop-patterns.stderr b/src/test/ui/unreachable/unreachable-loop-patterns.stderr similarity index 73% rename from src/test/ui/reachable/unreachable-loop-patterns.stderr rename to src/test/ui/unreachable/unreachable-loop-patterns.stderr index bb5103320d2cf..254d1178d142e 100644 --- a/src/test/ui/reachable/unreachable-loop-patterns.stderr +++ b/src/test/ui/unreachable/unreachable-loop-patterns.stderr @@ -1,17 +1,17 @@ error: unreachable pattern - --> $DIR/unreachable-loop-patterns.rs:18:9 + --> $DIR/unreachable-loop-patterns.rs:20:9 | LL | for _ in unimplemented!() as Void {} | ^ | note: lint level defined here - --> $DIR/unreachable-loop-patterns.rs:5:9 + --> $DIR/unreachable-loop-patterns.rs:7:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/unreachable-loop-patterns.rs:18:14 + --> $DIR/unreachable-loop-patterns.rs:20:14 | LL | for _ in unimplemented!() as Void {} | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/reachable/unreachable-try-pattern.rs b/src/test/ui/unreachable/unreachable-try-pattern.rs similarity index 94% rename from src/test/ui/reachable/unreachable-try-pattern.rs rename to src/test/ui/unreachable/unreachable-try-pattern.rs index 23360e73f4a3a..cbc5fcee2f035 100644 --- a/src/test/ui/reachable/unreachable-try-pattern.rs +++ b/src/test/ui/unreachable/unreachable-try-pattern.rs @@ -1,4 +1,4 @@ -// check-pass +// build-pass (FIXME(62277): could be check-pass?) #![feature(never_type, exhaustive_patterns)] #![warn(unreachable_code)] #![warn(unreachable_patterns)] diff --git a/src/test/ui/reachable/unreachable-try-pattern.stderr b/src/test/ui/unreachable/unreachable-try-pattern.stderr similarity index 100% rename from src/test/ui/reachable/unreachable-try-pattern.stderr rename to src/test/ui/unreachable/unreachable-try-pattern.stderr diff --git a/src/test/ui/reachable/unreachable-variant.rs b/src/test/ui/unreachable/unreachable-variant.rs similarity index 100% rename from src/test/ui/reachable/unreachable-variant.rs rename to src/test/ui/unreachable/unreachable-variant.rs diff --git a/src/test/ui/reachable/unreachable-variant.stderr b/src/test/ui/unreachable/unreachable-variant.stderr similarity index 100% rename from src/test/ui/reachable/unreachable-variant.stderr rename to src/test/ui/unreachable/unreachable-variant.stderr diff --git a/src/test/ui/reachable/unwarned-match-on-never.rs b/src/test/ui/unreachable/unwarned-match-on-never.rs similarity index 100% rename from src/test/ui/reachable/unwarned-match-on-never.rs rename to src/test/ui/unreachable/unwarned-match-on-never.rs diff --git a/src/test/ui/reachable/unwarned-match-on-never.stderr b/src/test/ui/unreachable/unwarned-match-on-never.stderr similarity index 100% rename from src/test/ui/reachable/unwarned-match-on-never.stderr rename to src/test/ui/unreachable/unwarned-match-on-never.stderr diff --git a/src/test/ui/unsized/unsized-bare-typaram.stderr b/src/test/ui/unsized/unsized-bare-typaram.stderr index bd97b0203b510..e56176690a113 100644 --- a/src/test/ui/unsized/unsized-bare-typaram.stderr +++ b/src/test/ui/unsized/unsized-bare-typaram.stderr @@ -4,12 +4,11 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim LL | fn bar() { } | --- - required by this bound in `bar` LL | fn foo() { bar::() } - | -- ^ doesn't have a size known at compile-time - | | - | help: consider further restricting this bound: `T: std::marker::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 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 341d3e4cc2df2..dff934834ef2c 100644 --- a/src/test/ui/unsized/unsized-enum.stderr +++ b/src/test/ui/unsized/unsized-enum.stderr @@ -5,12 +5,11 @@ 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: consider further restricting this bound: `T: std::marker::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 error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-enum2.stderr b/src/test/ui/unsized/unsized-enum2.stderr index e85b6d662f9d5..cdd5747d86b0f 100644 --- a/src/test/ui/unsized/unsized-enum2.stderr +++ b/src/test/ui/unsized/unsized-enum2.stderr @@ -1,53 +1,45 @@ error[E0277]: the size for values of type `W` cannot be known at compilation time --> $DIR/unsized-enum2.rs:23:8 | -LL | enum E { - | -- help: consider further restricting this bound: `W: std::marker::Sized +` -LL | // parameter LL | VA(W), | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `W` = note: to learn more, visit + = help: consider adding a `where W: std::marker::Sized` bound = note: no field of an enum variant may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized-enum2.rs:25:8 | -LL | enum E { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` -... LL | VB{x: X}, | ^^^^ 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: no field of an enum variant may have a dynamically sized type error[E0277]: the size for values of type `Y` cannot be known at compilation time --> $DIR/unsized-enum2.rs:27:15 | -LL | enum E { - | -- help: consider further restricting this bound: `Y: std::marker::Sized +` -... LL | VC(isize, Y), | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Y` = note: to learn more, visit + = help: consider adding a `where Y: std::marker::Sized` bound = note: no field of an enum variant may have a dynamically sized type error[E0277]: the size for values of type `Z` cannot be known at compilation time --> $DIR/unsized-enum2.rs:29:18 | -LL | enum E { - | -- help: consider further restricting this bound: `Z: std::marker::Sized +` -... LL | VD{u: isize, x: Z}, | ^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Z` = note: to learn more, visit + = help: consider adding a `where Z: std::marker::Sized` bound = note: no field of an enum variant may have a dynamically sized type error[E0277]: the size for values of type `[u8]` cannot be known at compilation time 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 280b8fd43cab0..1a726bb089f6e 100644 --- a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr @@ -5,12 +5,11 @@ LL | struct S5(Y); | ---------------- required by `S5` LL | LL | impl S5 { - | -- ^^^^^ doesn't have a size known at compile-time - | | - | help: consider further restricting this bound: `X: std::marker::Sized +` + | ^^^^^ 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 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 2894d5d56710d..0d4776ff6c25b 100644 --- a/src/test/ui/unsized/unsized-struct.stderr +++ b/src/test/ui/unsized/unsized-struct.stderr @@ -5,12 +5,11 @@ 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: consider further restricting this bound: `T: std::marker::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 error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/unsized-struct.rs:13:24 @@ -19,12 +18,11 @@ 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 - | | - | help: consider further restricting this bound: `T: std::marker::Sized +` + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `Bar`, 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 because it appears within the type `Bar` 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 ba1550439c0d9..f399f8ded1085 100644 --- a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr @@ -5,12 +5,11 @@ LL | struct S5(Y); | ---------------- required by `S5` LL | LL | impl T3 for S5 { - | -- ^^^^^ doesn't have a size known at compile-time - | | - | help: consider further restricting this bound: `X: std::marker::Sized +` + | ^^^^^ 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 error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr index 41371d63f9e53..ee0d5ccccfe11 100644 --- a/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr @@ -2,12 +2,11 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized-trait-impl-trait-arg.rs:8:17 | LL | impl T2 for S4 { - | -- ^^^^^ doesn't have a size known at compile-time - | | - | help: consider further restricting this bound: `X: std::marker::Sized +` + | ^^^^^ 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 error: aborting due to previous error diff --git a/src/test/ui/unsized3.stderr b/src/test/ui/unsized3.stderr index 232296ad09126..c821a08f6b585 100644 --- a/src/test/ui/unsized3.stderr +++ b/src/test/ui/unsized3.stderr @@ -1,8 +1,6 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:7:13 | -LL | fn f1(x: &X) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f2::(x); | ^ doesn't have a size known at compile-time ... @@ -11,12 +9,11 @@ LL | fn f2(x: &X) { | = 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 error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:18:13 | -LL | fn f3(x: &X) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f4::(x); | ^ doesn't have a size known at compile-time ... @@ -25,6 +22,7 @@ LL | fn f4(x: &X) { | = 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 error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:33:8 @@ -32,38 +30,35 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim LL | fn f5(x: &Y) {} | -- - required by this bound in `f5` ... -LL | fn f8(x1: &S, x2: &S) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f5(x1); | ^^ 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` error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:40:8 | -LL | fn f9(x1: Box>) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f5(&(*x1, 34)); | ^^^^^^^^^^ 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: only the last element of a tuple may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:45:9 | -LL | fn f10(x1: Box>) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f5(&(32, *x1)); | ^^^^^^^^^ 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: tuples must have a statically known size to be initialized @@ -74,13 +69,12 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim LL | fn f5(x: &Y) {} | -- - required by this bound in `f5` ... -LL | fn f10(x1: Box>) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f5(&(32, *x1)); | ^^^^^^^^^^ 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)` diff --git a/src/test/ui/unsized5.stderr b/src/test/ui/unsized5.stderr index bfd3f4aa691eb..6dce9a046066f 100644 --- a/src/test/ui/unsized5.stderr +++ b/src/test/ui/unsized5.stderr @@ -1,26 +1,23 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized5.rs:4:5 | -LL | struct S1 { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f1: X, | ^^^^^ 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: only the last field of a struct may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized5.rs:10:5 | -LL | struct S2 { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` -LL | f: isize, LL | g: X, | ^^^^ 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: only the last field of a struct may have a dynamically sized type error[E0277]: the size for values of type `str` cannot be known at compilation time @@ -46,25 +43,23 @@ LL | f: [u8], error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized5.rs:25:8 | -LL | enum E { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | V1(X, isize), | ^ 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: no field of an enum variant may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized5.rs:29:8 | -LL | enum F { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | V2{f1: X, f: isize}, | ^^^^^ 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: no field of an enum variant may have a dynamically sized type error: aborting due to 6 previous errors diff --git a/src/test/ui/unsized6.stderr b/src/test/ui/unsized6.stderr index 95acd987a5a27..a6a26573e7c59 100644 --- a/src/test/ui/unsized6.stderr +++ b/src/test/ui/unsized6.stderr @@ -1,148 +1,129 @@ error[E0277]: the size for values of type `Y` cannot be known at compilation time --> $DIR/unsized6.rs:9:9 | -LL | fn f1(x: &X) { - | -- help: consider further restricting this bound: `Y: std::marker::Sized +` -... LL | let y: Y; | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Y` = note: to learn more, visit + = help: consider adding a `where Y: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:7:12 | -LL | fn f1(x: &X) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` -LL | let _: W; // <-- this is OK, no bindings created, no initializer. LL | let _: (isize, (X, isize)); | ^^^^^^^^^^^^^^^^^^^ 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: only the last element of a tuple may have a dynamically sized type error[E0277]: the size for values of type `Z` cannot be known at compilation time --> $DIR/unsized6.rs:11:12 | -LL | fn f1(x: &X) { - | -- help: consider further restricting this bound: `Z: std::marker::Sized +` -... LL | let y: (isize, (Z, usize)); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Z` = note: to learn more, visit + = help: consider adding a `where Z: std::marker::Sized` bound = note: only the last element of a tuple may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:15:9 | -LL | fn f2(x: &X) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | let y: X; | ^ 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: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `Y` cannot be known at compilation time --> $DIR/unsized6.rs:17:12 | -LL | fn f2(x: &X) { - | -- help: consider further restricting this bound: `Y: std::marker::Sized +` -... LL | let y: (isize, (Y, isize)); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Y` = note: to learn more, visit + = help: consider adding a `where Y: std::marker::Sized` bound = note: only the last element of a tuple may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:22:9 | -LL | fn f3(x1: Box, x2: Box, x3: Box) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | let y: X = *x1; | ^ 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: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:24:9 | -LL | fn f3(x1: Box, x2: Box, x3: Box) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` -... LL | let y = *x2; | ^ 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: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:26:10 | -LL | fn f3(x1: Box, x2: Box, x3: Box) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` -... LL | let (y, z) = (*x3, 4); | ^ 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: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:30:9 | -LL | fn f4(x1: Box, x2: Box, x3: Box) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | let y: X = *x1; | ^ 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: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:32:9 | -LL | fn f4(x1: Box, x2: Box, x3: Box) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` -... LL | let y = *x2; | ^ 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: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:34:10 | -LL | fn f4(x1: Box, x2: Box, x3: Box) { - | -- help: consider further restricting this bound: `X: std::marker::Sized +` -... LL | let (y, z) = (*x3, 4); | ^ 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: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature @@ -150,12 +131,11 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized6.rs:38:18 | LL | fn g1(x: X) {} - | -- ^ doesn't have a size known at compile-time - | | - | help: consider further restricting this bound: `X: std::marker::Sized +` + | ^ 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: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature @@ -163,12 +143,11 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized6.rs:40:22 | LL | fn g2(x: X) {} - | -- ^ doesn't have a size known at compile-time - | | - | help: consider further restricting this bound: `X: std::marker::Sized +` + | ^ 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: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature diff --git a/src/test/ui/unsized7.stderr b/src/test/ui/unsized7.stderr index c77503a6f87aa..bb83b1811844a 100644 --- a/src/test/ui/unsized7.stderr +++ b/src/test/ui/unsized7.stderr @@ -2,12 +2,11 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized7.rs:12:21 | LL | impl T1 for S3 { - | -- ^^^^^ doesn't have a size known at compile-time - | | - | help: consider further restricting this bound: `X: std::marker::Sized +` + | ^^^^^ 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 error: aborting due to previous error diff --git a/src/test/ui/use/issue-18986.stderr b/src/test/ui/use/issue-18986.stderr index 6c23178c70011..14e1bb624033b 100644 --- a/src/test/ui/use/issue-18986.stderr +++ b/src/test/ui/use/issue-18986.stderr @@ -6,4 +6,3 @@ LL | Trait { x: 42 } => () error: aborting due to previous error -For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/use/use-meta-mismatch.rs b/src/test/ui/use/use-meta-mismatch.rs index 975209efb0c1b..459216a17e4f3 100644 --- a/src/test/ui/use/use-meta-mismatch.rs +++ b/src/test/ui/use/use-meta-mismatch.rs @@ -1,4 +1,4 @@ -// error-pattern:can't find crate for `fake_crate` +// error-pattern:can't find crate for `extra` extern crate fake_crate as extra; diff --git a/src/test/ui/use/use-meta-mismatch.stderr b/src/test/ui/use/use-meta-mismatch.stderr index 62b71fe8e12f4..877ac464de782 100644 --- a/src/test/ui/use/use-meta-mismatch.stderr +++ b/src/test/ui/use/use-meta-mismatch.stderr @@ -1,4 +1,4 @@ -error[E0463]: can't find crate for `fake_crate` +error[E0463]: can't find crate for `extra` --> $DIR/use-meta-mismatch.rs:3:1 | LL | extern crate fake_crate as extra; diff --git a/src/test/ui/variance/variance-btree-invariant-types.stderr b/src/test/ui/variance/variance-btree-invariant-types.stderr index 0f93927683ea6..49222fc7fa627 100644 --- a/src/test/ui/variance/variance-btree-invariant-types.stderr +++ b/src/test/ui/variance/variance-btree-invariant-types.stderr @@ -6,7 +6,7 @@ LL | v | = note: expected type `std::collections::btree_map::IterMut<'_, &'new (), _>` found type `std::collections::btree_map::IterMut<'_, &'static (), _>` -note: the lifetime `'new` as defined on the function body at 3:21... +note: the lifetime 'new as defined on the function body at 3:21... --> $DIR/variance-btree-invariant-types.rs:3:21 | LL | fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> { @@ -21,7 +21,7 @@ LL | v | = note: expected type `std::collections::btree_map::IterMut<'_, _, &'new ()>` found type `std::collections::btree_map::IterMut<'_, _, &'static ()>` -note: the lifetime `'new` as defined on the function body at 6:21... +note: the lifetime 'new as defined on the function body at 6:21... --> $DIR/variance-btree-invariant-types.rs:6:21 | LL | fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (), &'new ()> { @@ -36,7 +36,7 @@ LL | v | = note: expected type `std::collections::btree_map::IterMut<'_, &'static (), _>` found type `std::collections::btree_map::IterMut<'_, &'new (), _>` -note: the lifetime `'new` as defined on the function body at 9:24... +note: the lifetime 'new as defined on the function body at 9:24... --> $DIR/variance-btree-invariant-types.rs:9:24 | LL | fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &'static (), ()> { @@ -51,7 +51,7 @@ LL | v | = note: expected type `std::collections::btree_map::IterMut<'_, _, &'static ()>` found type `std::collections::btree_map::IterMut<'_, _, &'new ()>` -note: the lifetime `'new` as defined on the function body at 12:24... +note: the lifetime 'new as defined on the function body at 12:24... --> $DIR/variance-btree-invariant-types.rs:12:24 | LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'static ()> { @@ -66,7 +66,7 @@ LL | v | = note: expected type `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>` found type `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>` -note: the lifetime `'new` as defined on the function body at 16:20... +note: the lifetime 'new as defined on the function body at 16:20... --> $DIR/variance-btree-invariant-types.rs:16:20 | LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) @@ -81,7 +81,7 @@ LL | v | = note: expected type `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>` found type `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>` -note: the lifetime `'new` as defined on the function body at 20:20... +note: the lifetime 'new as defined on the function body at 20:20... --> $DIR/variance-btree-invariant-types.rs:20:20 | LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) @@ -96,7 +96,7 @@ LL | v | = note: expected type `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>` found type `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>` -note: the lifetime `'new` as defined on the function body at 24:23... +note: the lifetime 'new as defined on the function body at 24:23... --> $DIR/variance-btree-invariant-types.rs:24:23 | LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>) @@ -111,7 +111,7 @@ LL | v | = note: expected type `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>` found type `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>` -note: the lifetime `'new` as defined on the function body at 28:23... +note: the lifetime 'new as defined on the function body at 28:23... --> $DIR/variance-btree-invariant-types.rs:28:23 | LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>) @@ -126,7 +126,7 @@ LL | v | = note: expected type `std::collections::btree_map::VacantEntry<'_, &'new (), _>` found type `std::collections::btree_map::VacantEntry<'_, &'static (), _>` -note: the lifetime `'new` as defined on the function body at 33:20... +note: the lifetime 'new as defined on the function body at 33:20... --> $DIR/variance-btree-invariant-types.rs:33:20 | LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>) @@ -141,7 +141,7 @@ LL | v | = note: expected type `std::collections::btree_map::VacantEntry<'_, _, &'new ()>` found type `std::collections::btree_map::VacantEntry<'_, _, &'static ()>` -note: the lifetime `'new` as defined on the function body at 37:20... +note: the lifetime 'new as defined on the function body at 37:20... --> $DIR/variance-btree-invariant-types.rs:37:20 | LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>) @@ -156,7 +156,7 @@ LL | v | = note: expected type `std::collections::btree_map::VacantEntry<'_, &'static (), _>` found type `std::collections::btree_map::VacantEntry<'_, &'new (), _>` -note: the lifetime `'new` as defined on the function body at 41:23... +note: the lifetime 'new as defined on the function body at 41:23... --> $DIR/variance-btree-invariant-types.rs:41:23 | LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>) @@ -171,7 +171,7 @@ LL | v | = note: expected type `std::collections::btree_map::VacantEntry<'_, _, &'static ()>` found type `std::collections::btree_map::VacantEntry<'_, _, &'new ()>` -note: the lifetime `'new` as defined on the function body at 45:23... +note: the lifetime 'new as defined on the function body at 45:23... --> $DIR/variance-btree-invariant-types.rs:45:23 | LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>) diff --git a/src/test/ui/variance/variance-contravariant-arg-object.stderr b/src/test/ui/variance/variance-contravariant-arg-object.stderr index 27017e5dc47d6..263c849e19981 100644 --- a/src/test/ui/variance/variance-contravariant-arg-object.stderr +++ b/src/test/ui/variance/variance-contravariant-arg-object.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected type `dyn Get<&'min i32>` found type `dyn Get<&'max i32>` -note: the lifetime `'min` as defined on the function body at 10:21... +note: the lifetime 'min as defined on the function body at 10:21... --> $DIR/variance-contravariant-arg-object.rs:10:21 | LL | fn get_min_from_max<'min, 'max>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27 --> $DIR/variance-contravariant-arg-object.rs:10:27 | LL | fn get_min_from_max<'min, 'max>(v: Box>) @@ -25,12 +25,12 @@ LL | v | = note: expected type `dyn Get<&'max i32>` found type `dyn Get<&'min i32>` -note: the lifetime `'min` as defined on the function body at 17:21... +note: the lifetime 'min as defined on the function body at 17:21... --> $DIR/variance-contravariant-arg-object.rs:17:21 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 17:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 17:27 --> $DIR/variance-contravariant-arg-object.rs:17:27 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) diff --git a/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr b/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr index 1752b3b36a484..ffe690dd22073 100644 --- a/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr +++ b/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::() | = note: expected type `Get<&'min i32>` found type `Get<&'max i32>` -note: the lifetime `'min` as defined on the function body at 10:21... +note: the lifetime 'min as defined on the function body at 10:21... --> $DIR/variance-contravariant-arg-trait-match.rs:10:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27 --> $DIR/variance-contravariant-arg-trait-match.rs:10:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::() | = note: expected type `Get<&'max i32>` found type `Get<&'min i32>` -note: the lifetime `'min` as defined on the function body at 16:21... +note: the lifetime 'min as defined on the function body at 16:21... --> $DIR/variance-contravariant-arg-trait-match.rs:16:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 16:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 16:27 --> $DIR/variance-contravariant-arg-trait-match.rs:16:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-contravariant-self-trait-match.stderr b/src/test/ui/variance/variance-contravariant-self-trait-match.stderr index e35aec4c0ce27..6f445d79bf5d2 100644 --- a/src/test/ui/variance/variance-contravariant-self-trait-match.stderr +++ b/src/test/ui/variance/variance-contravariant-self-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::<&'min G>(); | = note: expected type `Get` found type `Get` -note: the lifetime `'min` as defined on the function body at 10:21... +note: the lifetime 'min as defined on the function body at 10:21... --> $DIR/variance-contravariant-self-trait-match.rs:10:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27 --> $DIR/variance-contravariant-self-trait-match.rs:10:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::<&'max G>(); | = note: expected type `Get` found type `Get` -note: the lifetime `'min` as defined on the function body at 16:21... +note: the lifetime 'min as defined on the function body at 16:21... --> $DIR/variance-contravariant-self-trait-match.rs:16:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 16:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 16:27 --> $DIR/variance-contravariant-self-trait-match.rs:16:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-covariant-arg-object.stderr b/src/test/ui/variance/variance-covariant-arg-object.stderr index b986edb809f6c..94f80c2b657f5 100644 --- a/src/test/ui/variance/variance-covariant-arg-object.stderr +++ b/src/test/ui/variance/variance-covariant-arg-object.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected type `dyn Get<&'min i32>` found type `dyn Get<&'max i32>` -note: the lifetime `'min` as defined on the function body at 10:21... +note: the lifetime 'min as defined on the function body at 10:21... --> $DIR/variance-covariant-arg-object.rs:10:21 | LL | fn get_min_from_max<'min, 'max>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27 --> $DIR/variance-covariant-arg-object.rs:10:27 | LL | fn get_min_from_max<'min, 'max>(v: Box>) @@ -25,12 +25,12 @@ LL | v | = note: expected type `dyn Get<&'max i32>` found type `dyn Get<&'min i32>` -note: the lifetime `'min` as defined on the function body at 18:21... +note: the lifetime 'min as defined on the function body at 18:21... --> $DIR/variance-covariant-arg-object.rs:18:21 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 18:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 18:27 --> $DIR/variance-covariant-arg-object.rs:18:27 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) diff --git a/src/test/ui/variance/variance-covariant-arg-trait-match.stderr b/src/test/ui/variance/variance-covariant-arg-trait-match.stderr index aa383fcc26280..c0209edc91553 100644 --- a/src/test/ui/variance/variance-covariant-arg-trait-match.stderr +++ b/src/test/ui/variance/variance-covariant-arg-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::() | = note: expected type `Get<&'min i32>` found type `Get<&'max i32>` -note: the lifetime `'min` as defined on the function body at 10:21... +note: the lifetime 'min as defined on the function body at 10:21... --> $DIR/variance-covariant-arg-trait-match.rs:10:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27 --> $DIR/variance-covariant-arg-trait-match.rs:10:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::() | = note: expected type `Get<&'max i32>` found type `Get<&'min i32>` -note: the lifetime `'min` as defined on the function body at 17:21... +note: the lifetime 'min as defined on the function body at 17:21... --> $DIR/variance-covariant-arg-trait-match.rs:17:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 17:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 17:27 --> $DIR/variance-covariant-arg-trait-match.rs:17:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-covariant-self-trait-match.stderr b/src/test/ui/variance/variance-covariant-self-trait-match.stderr index a25d1044d4256..fe5fe105c6b3c 100644 --- a/src/test/ui/variance/variance-covariant-self-trait-match.stderr +++ b/src/test/ui/variance/variance-covariant-self-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::<&'min G>(); | = note: expected type `Get` found type `Get` -note: the lifetime `'min` as defined on the function body at 10:21... +note: the lifetime 'min as defined on the function body at 10:21... --> $DIR/variance-covariant-self-trait-match.rs:10:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27 --> $DIR/variance-covariant-self-trait-match.rs:10:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::<&'max G>(); | = note: expected type `Get` found type `Get` -note: the lifetime `'min` as defined on the function body at 17:21... +note: the lifetime 'min as defined on the function body at 17:21... --> $DIR/variance-covariant-self-trait-match.rs:17:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 17:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 17:27 --> $DIR/variance-covariant-self-trait-match.rs:17:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-invariant-arg-object.stderr b/src/test/ui/variance/variance-invariant-arg-object.stderr index 8ff1e23e8add8..50a8697d4392f 100644 --- a/src/test/ui/variance/variance-invariant-arg-object.stderr +++ b/src/test/ui/variance/variance-invariant-arg-object.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected type `dyn Get<&'min i32>` found type `dyn Get<&'max i32>` -note: the lifetime `'min` as defined on the function body at 7:21... +note: the lifetime 'min as defined on the function body at 7:21... --> $DIR/variance-invariant-arg-object.rs:7:21 | LL | fn get_min_from_max<'min, 'max>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 7:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 7:27 --> $DIR/variance-invariant-arg-object.rs:7:27 | LL | fn get_min_from_max<'min, 'max>(v: Box>) @@ -25,12 +25,12 @@ LL | v | = note: expected type `dyn Get<&'max i32>` found type `dyn Get<&'min i32>` -note: the lifetime `'min` as defined on the function body at 14:21... +note: the lifetime 'min as defined on the function body at 14:21... --> $DIR/variance-invariant-arg-object.rs:14:21 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 14:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 14:27 --> $DIR/variance-invariant-arg-object.rs:14:27 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) diff --git a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr b/src/test/ui/variance/variance-invariant-arg-trait-match.stderr index b58993737c783..c8a1111e6237d 100644 --- a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr +++ b/src/test/ui/variance/variance-invariant-arg-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::() | = note: expected type `Get<&'min i32>` found type `Get<&'max i32>` -note: the lifetime `'min` as defined on the function body at 7:21... +note: the lifetime 'min as defined on the function body at 7:21... --> $DIR/variance-invariant-arg-trait-match.rs:7:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 7:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 7:27 --> $DIR/variance-invariant-arg-trait-match.rs:7:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::() | = note: expected type `Get<&'max i32>` found type `Get<&'min i32>` -note: the lifetime `'min` as defined on the function body at 13:21... +note: the lifetime 'min as defined on the function body at 13:21... --> $DIR/variance-invariant-arg-trait-match.rs:13:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 13:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 13:27 --> $DIR/variance-invariant-arg-trait-match.rs:13:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-invariant-self-trait-match.stderr b/src/test/ui/variance/variance-invariant-self-trait-match.stderr index 4a1d4d28b4805..cb03d95f77104 100644 --- a/src/test/ui/variance/variance-invariant-self-trait-match.stderr +++ b/src/test/ui/variance/variance-invariant-self-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::<&'min G>(); | = note: expected type `Get` found type `Get` -note: the lifetime `'min` as defined on the function body at 7:21... +note: the lifetime 'min as defined on the function body at 7:21... --> $DIR/variance-invariant-self-trait-match.rs:7:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 7:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 7:27 --> $DIR/variance-invariant-self-trait-match.rs:7:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::<&'max G>(); | = note: expected type `Get` found type `Get` -note: the lifetime `'min` as defined on the function body at 13:21... +note: the lifetime 'min as defined on the function body at 13:21... --> $DIR/variance-invariant-self-trait-match.rs:13:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 13:27 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 13:27 --> $DIR/variance-invariant-self-trait-match.rs:13:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-regions-unused-direct.stderr b/src/test/ui/variance/variance-regions-unused-direct.stderr index cf375ccae8730..21ff475663c6c 100644 --- a/src/test/ui/variance/variance-regions-unused-direct.stderr +++ b/src/test/ui/variance/variance-regions-unused-direct.stderr @@ -4,7 +4,7 @@ error[E0392]: parameter `'a` is never used LL | struct Bivariant<'a>; | ^^ unused parameter | - = help: consider removing `'a`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `'a` or using a marker such as `std::marker::PhantomData` error[E0392]: parameter `'d` is never used --> $DIR/variance-regions-unused-direct.rs:7:19 @@ -12,7 +12,7 @@ error[E0392]: parameter `'d` is never used LL | struct Struct<'a, 'd> { | ^^ unused parameter | - = help: consider removing `'d`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `'d` or using a marker such as `std::marker::PhantomData` error: aborting due to 2 previous errors diff --git a/src/test/ui/variance/variance-regions-unused-indirect.stderr b/src/test/ui/variance/variance-regions-unused-indirect.stderr index 7c7ba69db2110..fd66217f692f1 100644 --- a/src/test/ui/variance/variance-regions-unused-indirect.stderr +++ b/src/test/ui/variance/variance-regions-unused-indirect.stderr @@ -4,7 +4,7 @@ error[E0392]: parameter `'a` is never used LL | enum Foo<'a> { | ^^ unused parameter | - = help: consider removing `'a`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `'a` or using a marker such as `std::marker::PhantomData` error[E0392]: parameter `'a` is never used --> $DIR/variance-regions-unused-indirect.rs:7:10 @@ -12,7 +12,7 @@ error[E0392]: parameter `'a` is never used LL | enum Bar<'a> { | ^^ unused parameter | - = help: consider removing `'a`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `'a` or using a marker such as `std::marker::PhantomData` error: aborting due to 2 previous errors diff --git a/src/test/ui/variance/variance-unused-region-param.stderr b/src/test/ui/variance/variance-unused-region-param.stderr index 4cd31358031d7..a96b2338bf428 100644 --- a/src/test/ui/variance/variance-unused-region-param.stderr +++ b/src/test/ui/variance/variance-unused-region-param.stderr @@ -4,7 +4,7 @@ error[E0392]: parameter `'a` is never used LL | struct SomeStruct<'a> { x: u32 } | ^^ unused parameter | - = help: consider removing `'a`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `'a` or using a marker such as `std::marker::PhantomData` error[E0392]: parameter `'a` is never used --> $DIR/variance-unused-region-param.rs:4:15 @@ -12,7 +12,7 @@ error[E0392]: parameter `'a` is never used LL | enum SomeEnum<'a> { Nothing } | ^^ unused parameter | - = help: consider removing `'a`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `'a` or using a marker such as `std::marker::PhantomData` error: aborting due to 2 previous errors diff --git a/src/test/ui/variance/variance-unused-type-param.stderr b/src/test/ui/variance/variance-unused-type-param.stderr index b648e3c1d5f52..883db46298624 100644 --- a/src/test/ui/variance/variance-unused-type-param.stderr +++ b/src/test/ui/variance/variance-unused-type-param.stderr @@ -4,7 +4,7 @@ error[E0392]: parameter `A` is never used LL | struct SomeStruct { x: u32 } | ^ unused parameter | - = help: consider removing `A`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `A` or using a marker such as `std::marker::PhantomData` error[E0392]: parameter `A` is never used --> $DIR/variance-unused-type-param.rs:9:15 @@ -12,7 +12,7 @@ error[E0392]: parameter `A` is never used LL | enum SomeEnum { Nothing } | ^ unused parameter | - = help: consider removing `A`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `A` or using a marker such as `std::marker::PhantomData` error[E0392]: parameter `T` is never used --> $DIR/variance-unused-type-param.rs:13:15 @@ -20,7 +20,7 @@ error[E0392]: parameter `T` is never used LL | enum ListCell { | ^ unused parameter | - = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + = help: consider removing `T` or using a marker such as `std::marker::PhantomData` error: aborting due to 3 previous errors diff --git a/src/test/ui/variance/variance-use-contravariant-struct-1.stderr b/src/test/ui/variance/variance-use-contravariant-struct-1.stderr index 618f56da512d6..7c433378df5c3 100644 --- a/src/test/ui/variance/variance-use-contravariant-struct-1.stderr +++ b/src/test/ui/variance/variance-use-contravariant-struct-1.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected type `SomeStruct<&'min ()>` found type `SomeStruct<&'max ()>` -note: the lifetime `'min` as defined on the function body at 8:8... +note: the lifetime 'min as defined on the function body at 8:8... --> $DIR/variance-use-contravariant-struct-1.rs:8:8 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 8:13 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 8:13 --> $DIR/variance-use-contravariant-struct-1.rs:8:13 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) diff --git a/src/test/ui/variance/variance-use-covariant-struct-1.stderr b/src/test/ui/variance/variance-use-covariant-struct-1.stderr index 0b3a8dcfc86f4..6ae7d12c4633f 100644 --- a/src/test/ui/variance/variance-use-covariant-struct-1.stderr +++ b/src/test/ui/variance/variance-use-covariant-struct-1.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected type `SomeStruct<&'max ()>` found type `SomeStruct<&'min ()>` -note: the lifetime `'min` as defined on the function body at 6:8... +note: the lifetime 'min as defined on the function body at 6:8... --> $DIR/variance-use-covariant-struct-1.rs:6:8 | LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 6:13 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 6:13 --> $DIR/variance-use-covariant-struct-1.rs:6:13 | LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>) diff --git a/src/test/ui/variance/variance-use-invariant-struct-1.stderr b/src/test/ui/variance/variance-use-invariant-struct-1.stderr index 31deefb535e94..793954e3a1f04 100644 --- a/src/test/ui/variance/variance-use-invariant-struct-1.stderr +++ b/src/test/ui/variance/variance-use-invariant-struct-1.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected type `SomeStruct<&'min ()>` found type `SomeStruct<&'max ()>` -note: the lifetime `'min` as defined on the function body at 8:8... +note: the lifetime 'min as defined on the function body at 8:8... --> $DIR/variance-use-invariant-struct-1.rs:8:8 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 8:13 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 8:13 --> $DIR/variance-use-invariant-struct-1.rs:8:13 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) @@ -25,12 +25,12 @@ LL | v | = note: expected type `SomeStruct<&'max ()>` found type `SomeStruct<&'min ()>` -note: the lifetime `'min` as defined on the function body at 15:8... +note: the lifetime 'min as defined on the function body at 15:8... --> $DIR/variance-use-invariant-struct-1.rs:15:8 | LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 15:13 +note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 15:13 --> $DIR/variance-use-invariant-struct-1.rs:15:13 | LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>) diff --git a/src/test/ui/variants/variant-used-as-type.stderr b/src/test/ui/variants/variant-used-as-type.stderr index fdfc044d81f6c..1138b69ae3bc3 100644 --- a/src/test/ui/variants/variant-used-as-type.stderr +++ b/src/test/ui/variants/variant-used-as-type.stderr @@ -24,4 +24,3 @@ LL | impl Ty {} error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/wf/issue-48638.rs b/src/test/ui/wf/issue-48638.rs deleted file mode 100644 index f078431033216..0000000000000 --- a/src/test/ui/wf/issue-48638.rs +++ /dev/null @@ -1,21 +0,0 @@ -// check-pass - -pub trait D {} -pub struct DT; -impl D for DT {} - -pub trait A: Sized { - type AS; -} - -pub struct As(R); - -pub struct AT; -impl A for AT { - type AS = As; -} - -#[repr(packed)] -struct S(>::AS); - -fn main() {} diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs deleted file mode 100644 index ffdb49a3be5c7..0000000000000 --- a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Check that we do not allow casts or coercions -// to object unsafe trait objects inside a Box - -#![feature(object_safe_for_dispatch)] - -trait Trait: Sized {} - -struct S; - -impl Trait for S {} - -fn takes_box(t: Box) {} - -fn main() { - Box::new(S) as Box; //~ ERROR E0038 - let t_box: Box = Box::new(S); //~ ERROR E0038 - takes_box(Box::new(S)); //~ ERROR E0038 -} diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr deleted file mode 100644 index 0b63aef2bce10..0000000000000 --- a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:33 - | -LL | let t_box: Box = Box::new(S); - | ^^^^^^^^^^^ the trait `Trait` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box` - = note: required by cast to type `std::boxed::Box` - -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15 - | -LL | takes_box(Box::new(S)); - | ^^^^^^^^^^^ the trait `Trait` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box` - = note: required by cast to type `std::boxed::Box<(dyn Trait + 'static)>` - -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:5 - | -LL | Box::new(S) as Box; - | ^^^^^^^^^^^ the trait `Trait` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box` - = note: required by cast to type `std::boxed::Box` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj.rs b/src/test/ui/wf/wf-convert-unsafe-trait-obj.rs deleted file mode 100644 index 143b854ed6b2d..0000000000000 --- a/src/test/ui/wf/wf-convert-unsafe-trait-obj.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Check that we do not allow casts or coercions -// to object unsafe trait objects by ref - -#![feature(object_safe_for_dispatch)] - -trait Trait: Sized {} - -struct S; - -impl Trait for S {} - -fn takes_trait(t: &dyn Trait) {} - -fn main() { - &S as &dyn Trait; //~ ERROR E0038 - let t: &dyn Trait = &S; //~ ERROR E0038 - takes_trait(&S); //~ ERROR E0038 -} diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr b/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr deleted file mode 100644 index 7aeefd731fb28..0000000000000 --- a/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj.rs:16:25 - | -LL | let t: &dyn Trait = &S; - | ^^ the trait `Trait` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S` - = note: required by cast to type `&dyn Trait` - -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj.rs:17:17 - | -LL | takes_trait(&S); - | ^^ the trait `Trait` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S` - = note: required by cast to type `&dyn Trait` - -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj.rs:15:5 - | -LL | &S as &dyn Trait; - | ^^ the trait `Trait` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S` - = note: required by cast to type `&dyn Trait` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/wf/wf-enum-bound.stderr b/src/test/ui/wf/wf-enum-bound.stderr index eaacd6b6881ef..d5632f4a9c24e 100644 --- a/src/test/ui/wf/wf-enum-bound.stderr +++ b/src/test/ui/wf/wf-enum-bound.stderr @@ -6,11 +6,12 @@ LL | trait ExtraCopy { } LL | LL | / enum SomeEnum LL | | where T: ExtraCopy - | | - help: consider further restricting type parameter `U`: `, U: std::marker::Copy` LL | | { LL | | SomeVariant(T,U) LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` + | + = help: consider adding a `where U: std::marker::Copy` bound 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 52882c460d228..51ee23fc5aa6d 100644 --- a/src/test/ui/wf/wf-enum-fields-struct-variant.stderr +++ b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr @@ -4,11 +4,10 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied LL | struct IsCopy { | --------------------- required by `IsCopy` ... -LL | enum AnotherEnum { - | - help: consider restricting this bound: `A: std::marker::Copy` -LL | AnotherVariant { LL | f: IsCopy | ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A` + | + = help: consider adding a `where A: std::marker::Copy` bound 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 0fea35d68ea6f..5f4e7c66f54ca 100644 --- a/src/test/ui/wf/wf-enum-fields.stderr +++ b/src/test/ui/wf/wf-enum-fields.stderr @@ -4,10 +4,10 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied LL | struct IsCopy { | --------------------- required by `IsCopy` ... -LL | enum SomeEnum { - | - help: consider restricting this bound: `A: std::marker::Copy` LL | SomeVariant(IsCopy) | ^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A` + | + = help: consider adding a `where A: std::marker::Copy` bound 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 9b8b04a7b86a3..4bc2e370f29fa 100644 --- a/src/test/ui/wf/wf-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-fn-where-clause.stderr @@ -4,13 +4,12 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied LL | trait ExtraCopy { } | ----------------------- required by `ExtraCopy` LL | -LL | fn foo() where T: ExtraCopy - | ^ - help: consider further restricting type parameter `U`: `, U: std::marker::Copy` - | _| - | | +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 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 6d71670e6a84c..ceafb4f61578b 100644 --- a/src/test/ui/wf/wf-impl-associated-type-trait.stderr +++ b/src/test/ui/wf/wf-impl-associated-type-trait.stderr @@ -4,10 +4,10 @@ error[E0277]: the trait bound `T: MyHash` is not satisfied LL | pub struct MySet { | -------------------------- required by `MySet` ... -LL | impl Foo for T { - | - help: consider restricting this bound: `T: MyHash` LL | type Bar = MySet; | ^^^^^^^^^^^^^^^^^^^^ the trait `MyHash` is not implemented for `T` + | + = help: consider adding a `where T: MyHash` bound 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 3798ba1ec6e75..e7432f8198734 100644 --- a/src/test/ui/wf/wf-in-fn-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-arg.stderr @@ -4,13 +4,12 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | struct MustBeCopy { | ------------------------- required by `MustBeCopy` ... -LL | fn bar(_: &MustBeCopy) - | ^ - help: consider restricting this bound: `T: std::marker::Copy` - | _| - | | +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 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 2e46ce4900033..005ffe84502de 100644 --- a/src/test/ui/wf/wf-in-fn-ret.stderr +++ b/src/test/ui/wf/wf-in-fn-ret.stderr @@ -4,13 +4,12 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | struct MustBeCopy { | ------------------------- required by `MustBeCopy` ... -LL | fn bar() -> MustBeCopy - | ^ - help: consider restricting this bound: `T: std::marker::Copy` - | _| - | | +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 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 db4fb9f97f52d..b4cd921040225 100644 --- a/src/test/ui/wf/wf-in-fn-type-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-type-arg.stderr @@ -4,11 +4,10 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | struct MustBeCopy { | ------------------------- required by `MustBeCopy` ... -LL | struct Bar { - | - help: consider restricting this bound: `T: std::marker::Copy` -LL | // needs T: Copy LL | x: fn(MustBeCopy) | ^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | + = help: consider adding a `where T: std::marker::Copy` bound 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 09f8aa2a20182..988fbed8e9107 100644 --- a/src/test/ui/wf/wf-in-fn-type-ret.stderr +++ b/src/test/ui/wf/wf-in-fn-type-ret.stderr @@ -4,11 +4,10 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | struct MustBeCopy { | ------------------------- required by `MustBeCopy` ... -LL | struct Foo { - | - help: consider restricting this bound: `T: std::marker::Copy` -LL | // needs T: 'static LL | x: fn() -> MustBeCopy | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | + = help: consider adding a `where T: std::marker::Copy` bound 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 979802dec4998..0af38ddcffea3 100644 --- a/src/test/ui/wf/wf-in-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-in-fn-where-clause.stderr @@ -6,10 +6,11 @@ LL | trait MustBeCopy { ... LL | / fn bar() LL | | where T: MustBeCopy - | | - help: consider further restricting type parameter `U`: `, U: std::marker::Copy` LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` + | + = help: consider adding a `where U: std::marker::Copy` bound 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 2711820d82c65..0f4b4e417ca4f 100644 --- a/src/test/ui/wf/wf-in-obj-type-trait.stderr +++ b/src/test/ui/wf/wf-in-obj-type-trait.stderr @@ -4,11 +4,10 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | struct MustBeCopy { | ------------------------- required by `MustBeCopy` ... -LL | struct Bar { - | - help: consider restricting this bound: `T: std::marker::Copy` -LL | // needs T: Copy LL | x: dyn Object> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | + = help: consider adding a `where T: std::marker::Copy` bound 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 21f825ac9ef9a..1e258864d0367 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 @@ -4,11 +4,11 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied LL | trait ExtraCopy { } | ----------------------- required by `ExtraCopy` ... -LL | impl Foo { - | - help: consider restricting this bound: `U: std::marker::Copy` 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 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 35b9093381329..4c389b3ef3ef2 100644 --- a/src/test/ui/wf/wf-inherent-impl-where-clause.stderr +++ b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr @@ -4,13 +4,12 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied LL | trait ExtraCopy { } | ----------------------- required by `ExtraCopy` ... -LL | impl Foo where T: ExtraCopy - | ^ - help: consider further restricting type parameter `U`: `, U: std::marker::Copy` - | _| - | | +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 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 93d16514a5078..3ec90f00448a9 100644 --- a/src/test/ui/wf/wf-static-method.stderr +++ b/src/test/ui/wf/wf-static-method.stderr @@ -4,12 +4,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | u | ^ | -note: ...the reference is valid for the lifetime `'a` as defined on the impl at 14:6... +note: ...the reference is valid for the lifetime 'a as defined on the impl at 14:6... --> $DIR/wf-static-method.rs:14:6 | LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { | ^^ -note: ...but the borrowed content is only valid for the lifetime `'b` as defined on the impl at 14:10 +note: ...but the borrowed content is only valid for the lifetime 'b as defined on the impl at 14:10 --> $DIR/wf-static-method.rs:14:10 | LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { @@ -21,12 +21,12 @@ error[E0478]: lifetime bound not satisfied LL | let me = Self::make_me(); | ^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'b` as defined on the impl at 23:10 +note: lifetime parameter instantiated with the lifetime 'b as defined on the impl at 23:10 --> $DIR/wf-static-method.rs:23:10 | LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { | ^^ -note: but lifetime parameter must outlive the lifetime `'a` as defined on the impl at 23:6 +note: but lifetime parameter must outlive the lifetime 'a as defined on the impl at 23:6 --> $DIR/wf-static-method.rs:23:6 | LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { @@ -38,12 +38,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | u | ^ | -note: ...the reference is valid for the lifetime `'a` as defined on the impl at 31:6... +note: ...the reference is valid for the lifetime 'a as defined on the impl at 31:6... --> $DIR/wf-static-method.rs:31:6 | LL | impl<'a, 'b> Evil<'a, 'b> { | ^^ -note: ...but the borrowed content is only valid for the lifetime `'b` as defined on the impl at 31:10 +note: ...but the borrowed content is only valid for the lifetime 'b as defined on the impl at 31:10 --> $DIR/wf-static-method.rs:31:10 | LL | impl<'a, 'b> Evil<'a, 'b> { @@ -55,7 +55,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` d LL | <()>::static_evil(b) | ^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 40:13... +note: first, the lifetime cannot outlive the lifetime 'b as defined on the function body at 40:13... --> $DIR/wf-static-method.rs:40:13 | LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { @@ -65,7 +65,7 @@ note: ...so that reference does not outlive borrowed content | LL | <()>::static_evil(b) | ^ -note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 40:9... +note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 40:9... --> $DIR/wf-static-method.rs:40:9 | LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { @@ -82,7 +82,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` d LL | ::static_evil(b) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 44:22... +note: first, the lifetime cannot outlive the lifetime 'b as defined on the function body at 44:22... --> $DIR/wf-static-method.rs:44:22 | LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { @@ -92,7 +92,7 @@ note: ...so that reference does not outlive borrowed content | LL | ::static_evil(b) | ^ -note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 44:18... +note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 44:18... --> $DIR/wf-static-method.rs:44:18 | LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { @@ -105,5 +105,5 @@ LL | ::static_evil(b) error: aborting due to 5 previous errors -Some errors have detailed explanations: E0312, E0478, E0495. +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-struct-bound.stderr b/src/test/ui/wf/wf-struct-bound.stderr index 2155977349256..2028a0baa17fb 100644 --- a/src/test/ui/wf/wf-struct-bound.stderr +++ b/src/test/ui/wf/wf-struct-bound.stderr @@ -6,11 +6,12 @@ LL | trait ExtraCopy { } LL | LL | / struct SomeStruct LL | | where T: ExtraCopy - | | - help: consider further restricting type parameter `U`: `, U: std::marker::Copy` LL | | { LL | | data: (T,U) LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` + | + = help: consider adding a `where U: std::marker::Copy` bound 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 6ac4f1e2da8d2..d2bff253678ee 100644 --- a/src/test/ui/wf/wf-struct-field.stderr +++ b/src/test/ui/wf/wf-struct-field.stderr @@ -4,10 +4,10 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied LL | struct IsCopy { | --------------------- required by `IsCopy` ... -LL | struct SomeStruct { - | - help: consider restricting this bound: `A: std::marker::Copy` LL | data: IsCopy | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A` + | + = help: consider adding a `where A: std::marker::Copy` bound 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 af0433fd22f6e..d5b2b5762a43a 100644 --- a/src/test/ui/wf/wf-trait-associated-type-bound.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-bound.stderr @@ -4,13 +4,12 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | trait ExtraCopy { } | ----------------------- required by `ExtraCopy` LL | -LL | trait SomeTrait { - | ^ - help: consider restricting this bound: `T: std::marker::Copy` - | _| - | | +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 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 93cb948cdbfcb..d8ab955048239 100644 --- a/src/test/ui/wf/wf-trait-associated-type-trait.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-trait.stderr @@ -3,12 +3,11 @@ error[E0277]: the trait bound `::Type1: std::marker::Copy` is | LL | struct IsCopy { x: T } | --------------------- required by `IsCopy` -LL | -LL | trait SomeTrait { - | - help: consider further restricting the associated type: `where ::Type1: std::marker::Copy` -LL | type Type1; +... LL | type Type2 = IsCopy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `::Type1` + | + = help: consider adding a `where ::Type1: std::marker::Copy` bound 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 13e2f8f590149..85f12b2de5489 100644 --- a/src/test/ui/wf/wf-trait-bound.stderr +++ b/src/test/ui/wf/wf-trait-bound.stderr @@ -6,10 +6,11 @@ LL | trait ExtraCopy { } LL | LL | / trait SomeTrait LL | | where T: ExtraCopy - | | - help: consider further restricting type parameter `U`: `, U: std::marker::Copy` LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` + | + = help: consider adding a `where U: std::marker::Copy` bound 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 9f3545b9c6a6b..4d0e1f2f0f4cc 100644 --- a/src/test/ui/wf/wf-trait-default-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-arg.stderr @@ -4,15 +4,14 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied LL | struct Bar { value: Box } | ----------------------- required by `Bar` ... -LL | fn bar(&self, x: &Bar) { - | ^ - help: consider further restricting `Self`: `where Self: std::cmp::Eq` - | _____| - | | +LL | / fn bar(&self, x: &Bar) { LL | | LL | | // LL | | // Here, Eq ought to be implemented. LL | | } | |_____^ the trait `std::cmp::Eq` is not implemented for `Self` + | + = help: consider adding a `where Self: std::cmp::Eq` bound 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 e32630a5a4a40..e82b76b61c4a9 100644 --- a/src/test/ui/wf/wf-trait-default-fn-ret.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-ret.stderr @@ -4,16 +4,15 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied LL | struct Bar { value: Box } | ----------------------- required by `Bar` ... -LL | fn bar(&self) -> Bar { - | ^ - help: consider further restricting `Self`: `where Self: std::cmp::Eq` - | _____| - | | +LL | / fn bar(&self) -> Bar { LL | | LL | | // LL | | // Here, Eq ought to be implemented. LL | | loop { } LL | | } | |_____^ the trait `std::cmp::Eq` is not implemented for `Self` + | + = help: consider adding a `where Self: std::cmp::Eq` bound 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 a443ff1bb6396..6504f6698d9b1 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 @@ -4,15 +4,14 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied LL | trait Bar { } | ---------------------- required by `Bar` ... -LL | fn bar(&self) where A: Bar { - | ^ - help: consider further restricting `Self`: `, Self: std::cmp::Eq` - | _____| - | | +LL | / fn bar(&self) where A: Bar { LL | | LL | | // LL | | // Here, Eq ought to be implemented. LL | | } | |_____^ the trait `std::cmp::Eq` is not implemented for `Self` + | + = help: consider adding a `where Self: std::cmp::Eq` bound 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 42a28ee676373..0887d4b2fcda2 100644 --- a/src/test/ui/wf/wf-trait-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-fn-arg.stderr @@ -5,10 +5,9 @@ LL | struct Bar { value: Box } | ----------------------- required by `Bar` ... LL | fn bar(&self, x: &Bar); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | | - | | help: consider further restricting `Self`: `where Self: std::cmp::Eq` - | the trait `std::cmp::Eq` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` + | + = help: consider adding a `where Self: std::cmp::Eq` bound 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 7ec4dbe0056b4..5555081498c61 100644 --- a/src/test/ui/wf/wf-trait-fn-ret.stderr +++ b/src/test/ui/wf/wf-trait-fn-ret.stderr @@ -5,10 +5,9 @@ LL | struct Bar { value: Box } | ----------------------- required by `Bar` ... LL | fn bar(&self) -> &Bar; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | | - | | help: consider further restricting `Self`: `where Self: std::cmp::Eq` - | the trait `std::cmp::Eq` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` + | + = help: consider adding a `where Self: std::cmp::Eq` bound 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 256edb5b2ca1d..5e8fd8982390d 100644 --- a/src/test/ui/wf/wf-trait-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-trait-fn-where-clause.stderr @@ -5,10 +5,9 @@ LL | struct Bar { value: Box } | ----------------------- required by `Bar` ... LL | fn bar(&self) where Self: Sized, Bar: Copy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | | - | | help: consider further restricting `Self`: `, Self: std::cmp::Eq` - | the trait `std::cmp::Eq` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` + | + = help: consider adding a `where Self: std::cmp::Eq` bound 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 a61b8dd3a3849..377ca640536cf 100644 --- a/src/test/ui/wf/wf-trait-superbound.stderr +++ b/src/test/ui/wf/wf-trait-superbound.stderr @@ -4,12 +4,11 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | trait ExtraCopy { } | ----------------------- required by `ExtraCopy` LL | -LL | trait SomeTrait: ExtraCopy { - | ^ - help: consider restricting this bound: `T: std::marker::Copy` - | _| - | | +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 error: aborting due to previous error diff --git a/src/test/ui/wf/wf-unsafe-trait-obj-match.rs b/src/test/ui/wf/wf-unsafe-trait-obj-match.rs deleted file mode 100644 index c8731a8ecafa4..0000000000000 --- a/src/test/ui/wf/wf-unsafe-trait-obj-match.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Check that we do not allow coercions to object -// unsafe trait objects in match arms - -#![feature(object_safe_for_dispatch)] - -trait Trait: Sized {} - -struct S; - -impl Trait for S {} - -struct R; - -impl Trait for R {} - -fn opt() -> Option<()> { - Some(()) -} - -fn main() { - match opt() { - Some(()) => &S, - None => &R, //~ ERROR E0308 - } - let t: &dyn Trait = match opt() { //~ ERROR E0038 - Some(()) => &S, //~ ERROR E0038 - None => &R, - }; -} diff --git a/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr b/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr deleted file mode 100644 index 185b1e6c36b55..0000000000000 --- a/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr +++ /dev/null @@ -1,38 +0,0 @@ -error[E0308]: match arms have incompatible types - --> $DIR/wf-unsafe-trait-obj-match.rs:23:17 - | -LL | / match opt() { -LL | | Some(()) => &S, - | | -- this is found to be of type `&S` -LL | | None => &R, - | | ^^ expected struct `S`, found struct `R` -LL | | } - | |_____- `match` arms have incompatible types - | - = note: expected type `&S` - found type `&R` - -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-unsafe-trait-obj-match.rs:26:21 - | -LL | Some(()) => &S, - | ^^ the trait `Trait` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S` - = note: required by cast to type `&dyn Trait` - -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-unsafe-trait-obj-match.rs:25:25 - | -LL | let t: &dyn Trait = match opt() { - | ^^^^^^^^^^^ the trait `Trait` cannot be made into an object - | - = note: the trait cannot require that `Self : Sized` - = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&R` - = note: required by cast to type `&dyn Trait` - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0038, E0308. -For more information about an error, try `rustc --explain E0038`. 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 995b544600389..727c9b8e06721 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 @@ -4,11 +4,10 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | fn require_copy(x: T) {} | ------------ ---- required by this bound in `require_copy` ... -LL | impl Foo { - | - help: consider restricting this bound: `T: std::marker::Copy` -... LL | require_copy(self.x); | ^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | + = help: consider adding a `where T: std::marker::Copy` bound 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 fe575f3a28a9e..1c1937c3074db 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 @@ -4,11 +4,10 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | fn require_copy(x: T) {} | ------------ ---- required by this bound in `require_copy` ... -LL | impl Foo for Bar { - | - help: consider restricting this bound: `T: std::marker::Copy` -... LL | require_copy(self.x); | ^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | + = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index c0d2deab2f8ba..f41e7dd17ede6 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -399,7 +399,6 @@ impl Builder { fn add_packages_to(&mut self, manifest: &mut Manifest) { let mut package = |name, targets| self.package(name, &mut manifest.pkg, targets); package("rustc", HOSTS); - package("rustc-dev", HOSTS); package("cargo", HOSTS); package("rust-mingw", MINGW); package("rust-std", TARGETS); @@ -427,13 +426,6 @@ impl Builder { "rls-preview", "rust-src", "llvm-tools-preview", "lldb-preview", "rust-analysis", "miri-preview" ]); - - // The compiler libraries are not stable for end users, but `rustc-dev` was only recently - // split out of `rust-std`. We'll include it by default as a transition for nightly users. - if self.rust_release == "nightly" { - self.extend_profile("default", &mut manifest.profiles, &["rustc-dev"]); - self.extend_profile("complete", &mut manifest.profiles, &["rustc-dev"]); - } } fn add_renames_to(&self, manifest: &mut Manifest) { @@ -489,15 +481,6 @@ impl Builder { components.push(host_component("rust-mingw")); } - // The compiler libraries are not stable for end users, but `rustc-dev` was only recently - // split out of `rust-std`. We'll include it by default as a transition for nightly users, - // but ship it as an optional component on the beta and stable channels. - if self.rust_release == "nightly" { - components.push(host_component("rustc-dev")); - } else { - extensions.push(host_component("rustc-dev")); - } - // Tools are always present in the manifest, // but might be marked as unavailable if they weren't built. extensions.extend(vec![ @@ -515,11 +498,6 @@ impl Builder { .filter(|&&target| target != host) .map(|target| Component::from_str("rust-std", target)) ); - extensions.extend( - HOSTS.iter() - .filter(|&&target| target != host) - .map(|target| Component::from_str("rustc-dev", target)) - ); extensions.push(Component::from_str("rust-src", "*")); // If the components/extensions don't actually exist for this @@ -556,14 +534,6 @@ impl Builder { dst.insert(profile_name.to_owned(), pkgs.iter().map(|s| (*s).to_owned()).collect()); } - fn extend_profile(&mut self, - profile_name: &str, - dst: &mut BTreeMap>, - pkgs: &[&str]) { - dst.get_mut(profile_name).expect("existing profile") - .extend(pkgs.iter().map(|s| (*s).to_owned())); - } - fn package(&mut self, pkgname: &str, dst: &mut BTreeMap, diff --git a/src/tools/cargo b/src/tools/cargo index 3ba5f27170db1..ab6fa8908c9b6 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 3ba5f27170db10af7a92f2b682e049397197b8fa +Subproject commit ab6fa8908c9b6c8f7e2249231c395eebfbc49891 diff --git a/src/tools/clippy b/src/tools/clippy index 8ab24d76dd699..edd90473ec5ba 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 8ab24d76dd6990394e72e94d08021df9a7e4e6c9 +Subproject commit edd90473ec5ba29b9ae1ee706c982e7046a6e63e diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 2358a065d62d1..edb9eb7d860e2 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -100,7 +100,6 @@ pub enum PassMode { Check, Build, Run, - RunFail, } impl FromStr for PassMode { @@ -121,7 +120,6 @@ impl fmt::Display for PassMode { PassMode::Check => "check", PassMode::Build => "build", PassMode::Run => "run", - PassMode::RunFail => "run-fail", }; fmt::Display::fmt(s, f) } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 0309488506584..48dd68d0f61ee 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -141,10 +141,7 @@ impl EarlyProps { if config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln) { props.ignore = Ignore::Ignore; } - // FIXME: Re-enable run-fail once panics are handled correctly - if config.target.contains("emscripten") && config.mode == common::RunFail { - props.ignore = Ignore::Ignore; - } + } if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoGdbLldb) && @@ -613,11 +610,6 @@ impl TestProps { panic!("`run-pass` header is only supported in UI tests") } Some(PassMode::Run) - } else if config.parse_name_directive(ln, "run-fail") { - if config.mode != Mode::Ui { - panic!("`run-fail` header is only supported in UI tests") - } - Some(PassMode::RunFail) } else { None }; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index ea31f37c7a52b..baed27dd15152 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -326,14 +326,6 @@ impl<'test> TestCx<'test> { self.props.pass_mode(self.config) } - fn should_run(&self) -> bool { - let pass_mode = self.pass_mode(); - match self.config.mode { - Ui => pass_mode == Some(PassMode::Run) || pass_mode == Some(PassMode::RunFail), - mode => panic!("unimplemented for mode {:?}", mode), - } - } - fn should_run_successfully(&self) -> bool { let pass_mode = self.pass_mode(); match self.config.mode { @@ -1542,7 +1534,7 @@ impl<'test> TestCx<'test> { fn compile_test(&self) -> ProcRes { // Only use `make_exe_name` when the test ends up being executed. let will_execute = match self.config.mode { - Ui => self.should_run(), + Ui => self.should_run_successfully(), Incremental => self.revision.unwrap().starts_with("r"), RunFail | RunPassValgrind | MirOpt | DebugInfoCdb | DebugInfoGdbLldb | DebugInfoGdb | DebugInfoLldb => true, @@ -3115,7 +3107,7 @@ impl<'test> TestCx<'test> { let expected_errors = errors::load_errors(&self.testpaths.file, self.revision); - if self.should_run() { + 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) @@ -3128,14 +3120,8 @@ impl<'test> TestCx<'test> { &proc_res, ); } - if self.should_run_successfully() { - if !proc_res.status.success() { - self.fatal_proc_rec("test run failed!", &proc_res); - } - } else { - if proc_res.status.success() { - self.fatal_proc_rec("test run succeeded!", &proc_res); - } + if !proc_res.status.success() { + self.fatal_proc_rec("test run failed!", &proc_res); } } diff --git a/src/tools/error_index_generator/build.rs b/src/tools/error_index_generator/build.rs index c59533da1dc39..592b3f14c85af 100644 --- a/src/tools/error_index_generator/build.rs +++ b/src/tools/error_index_generator/build.rs @@ -15,7 +15,7 @@ fn main() { 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); + let contents = format!("(|| {{\n{}\n}})();", file); fs::write(&out_dir.join(&format!("error_{}.rs", idx)), &contents).unwrap(); diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 79c98b780eb65..e8a7252cb767c 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -126,6 +126,7 @@ fn check(cache: &mut Cache, // FIXME(#32129) if file.ends_with("std/string/struct.String.html") || file.ends_with("interpret/struct.ImmTy.html") || + file.ends_with("symbol/struct.InternedString.html") || file.ends_with("ast/struct.ThinVec.html") || file.ends_with("util/struct.ThinVec.html") || file.ends_with("layout/struct.TyLayout.html") || diff --git a/src/tools/miri b/src/tools/miri index fccb239824880..130f9488d3b86 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit fccb2398248802a268fcda544ff3945247ef2119 +Subproject commit 130f9488d3b861e02c9282b686eec717e30912cf diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 4383cd9d5be43..7cf3cc7663b47 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -143,7 +143,7 @@ def issue( cc @{}, do you think you would have time to do the follow-up work? If so, that would be great! - cc @{}, the PR reviewer, and nominating for compiler team prioritization. + cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization. ''').format( relevant_pr_number, tool, status_description, diff --git a/src/tools/rls b/src/tools/rls index a18df16181947..80a1d340f7d65 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit a18df16181947edd5eb593ea0f2321e0035448ee +Subproject commit 80a1d340f7d65b466bd3e0513c6b4b53498de2ff diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index a78cbdc2c4c6a..980c9753761ed 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -24,7 +24,6 @@ features = [ "jobapi", "jobapi2", "knownfolders", - "libloaderapi", "lmcons", "memoryapi", "minschannel", diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 33e3667085e4c..afb1ee1c14594 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 33e3667085e4c73d4391c6168552458eb47664de +Subproject commit afb1ee1c14594aed5bb4a762b357b01f13c9de10 diff --git a/src/tools/tidy/src/debug_artifacts.rs b/src/tools/tidy/src/debug_artifacts.rs deleted file mode 100644 index ee555a3e5bda7..0000000000000 --- a/src/tools/tidy/src/debug_artifacts.rs +++ /dev/null @@ -1,24 +0,0 @@ -//! Tidy check to prevent creation of unnecessary debug artifacts. - -use std::path::{Path, PathBuf}; - -const GRAPHVIZ_POSTFLOW_MSG: &'static str = - "`borrowck_graphviz_postflow` attribute in test"; - -pub fn check(path: &Path, bad: &mut bool) { - let test_dir: PathBuf = path.join("test"); - - super::walk(&test_dir, &mut super::filter_dirs, &mut |entry, contents| { - let filename = entry.path(); - let is_rust = filename.extension().map_or(false, |ext| ext == "rs"); - if !is_rust { - return; - } - - for (i, line) in contents.lines().enumerate() { - if line.contains("borrowck_graphviz_postflow") { - tidy_error!(bad, "{}:{}: {}", filename.display(), i + 1, GRAPHVIZ_POSTFLOW_MSG); - } - } - }); -} diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 8e46ca6cd2990..1ed39f45d3e70 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -89,7 +89,6 @@ const WHITELIST: &[Crate<'_>] = &[ Crate("crc32fast"), Crate("crossbeam-deque"), Crate("crossbeam-epoch"), - Crate("crossbeam-queue"), Crate("crossbeam-utils"), Crate("datafrog"), Crate("dlmalloc"), diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs deleted file mode 100644 index 159baff184d1b..0000000000000 --- a/src/tools/tidy/src/error_codes_check.rs +++ /dev/null @@ -1,137 +0,0 @@ -//! Checks that all error codes have at least one test to prevent having error -//! codes that are silently not thrown by the compiler anymore. - -use std::collections::HashMap; -use std::ffi::OsStr; -use std::path::Path; - -// A few of those error codes can't be tested but all the others can and *should* be tested! -const WHITELIST: &[&str] = &[ - "E0183", - "E0227", - "E0279", - "E0280", - "E0311", - "E0313", - "E0314", - "E0315", - "E0377", - "E0456", - "E0461", - "E0462", - "E0464", - "E0465", - "E0472", - "E0473", - "E0474", - "E0475", - "E0476", - "E0479", - "E0480", - "E0481", - "E0482", - "E0483", - "E0484", - "E0485", - "E0486", - "E0487", - "E0488", - "E0489", - "E0514", - "E0519", - "E0523", - "E0526", - "E0554", - "E0570", - "E0629", - "E0630", - "E0640", - "E0717", - "E0727", - "E0729", -]; - -fn extract_error_codes(f: &str, error_codes: &mut HashMap) { - let mut reached_no_explanation = false; - let mut last_error_code = None; - - for line in f.lines() { - let s = line.trim(); - if s.starts_with('E') && s.ends_with(": r##\"") { - if let Some(err_code) = s.splitn(2, ':').next() { - let err_code = err_code.to_owned(); - last_error_code = Some(err_code.clone()); - if !error_codes.contains_key(&err_code) { - error_codes.insert(err_code, false); - } - } - } else if s.starts_with("```") && s.contains("compile_fail") && s.contains('E') { - if let Some(err_code) = s.splitn(2, 'E').skip(1).next() { - if let Some(err_code) = err_code.splitn(2, ',').next() { - let nb = error_codes.entry(format!("E{}", err_code)).or_insert(false); - *nb = true; - } - } - } else if s == ";" { - reached_no_explanation = true; - } else if reached_no_explanation && s.starts_with('E') { - if let Some(err_code) = s.splitn(2, ',').next() { - let err_code = err_code.to_owned(); - if !error_codes.contains_key(&err_code) { // this check should *never* fail! - error_codes.insert(err_code, false); - } - } - } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") { - if let Some(last) = last_error_code { - error_codes.get_mut(&last).map(|x| *x = true); - } - last_error_code = None; - } - } -} - -fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap) { - for line in f.lines() { - let s = line.trim(); - if s.starts_with("error[E") || s.starts_with("warning[E") { - if let Some(err_code) = s.splitn(2, ']').next() { - if let Some(err_code) = err_code.splitn(2, '[').skip(1).next() { - let nb = error_codes.entry(err_code.to_owned()).or_insert(false); - *nb = true; - } - } - } - } -} - -pub fn check(path: &Path, bad: &mut bool) { - println!("Checking which error codes lack tests..."); - let mut error_codes: HashMap = HashMap::new(); - super::walk(path, - &mut |path| super::filter_dirs(path), - &mut |entry, contents| { - let file_name = entry.file_name(); - if file_name == "error_codes.rs" { - extract_error_codes(contents, &mut error_codes); - } else if entry.path().extension() == Some(OsStr::new("stderr")) { - extract_error_codes_from_tests(contents, &mut error_codes); - } - }); - println!("Found {} error codes", error_codes.len()); - - let mut errors = Vec::new(); - for (err_code, nb) in &error_codes { - if !*nb && !WHITELIST.contains(&err_code.as_str()) { - errors.push(format!("Error code {} needs to have at least one UI test!", err_code)); - } - } - errors.sort(); - for err in &errors { - eprintln!("{}", err); - } - println!("Found {} error codes with no tests", errors.len()); - if !errors.is_empty() { - *bad = true; - } - println!("Done!"); -} diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index d9db68ff66efd..e01184e3658b5 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -31,7 +31,6 @@ macro_rules! tidy_error { pub mod bins; pub mod style; -pub mod debug_artifacts; pub mod errors; pub mod features; pub mod cargo; @@ -42,10 +41,10 @@ pub mod extdeps; pub mod ui_tests; pub mod unit_tests; pub mod unstable_book; -pub mod error_codes_check; fn filter_dirs(path: &Path) -> bool { let skip = [ + "src/llvm-emscripten", "src/llvm-project", "src/stdarch", "src/tools/cargo", @@ -54,9 +53,6 @@ fn filter_dirs(path: &Path) -> bool { "src/tools/rls", "src/tools/rust-installer", "src/tools/rustfmt", - - // Filter RLS output directories - "target/rls", ]; skip.iter().any(|p| path.ends_with(p)) } diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index de6b0c5b28d9d..a57238ad8148a 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -22,7 +22,6 @@ fn main() { let verbose = args.iter().any(|s| *s == "--verbose"); bins::check(&path, &mut bad); style::check(&path, &mut bad); - debug_artifacts::check(&path, &mut bad); errors::check(&path, &mut bad); cargo::check(&path, &mut bad); edition::check(&path, &mut bad); @@ -36,7 +35,6 @@ fn main() { deps::check_whitelist(&path, &cargo, &mut bad); extdeps::check(&path, &mut bad); ui_tests::check(&path, &mut bad); - error_codes_check::check(&path, &mut bad); if bad { eprintln!("some tidy checks failed"); diff --git a/triagebot.toml b/triagebot.toml index f0e3a99037b02..f3509897bdf9c 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -3,19 +3,7 @@ allow-unauthenticated = [ "C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*", "F-*", "requires-nightly", # I-* without I-nominated - "I-*", "!I-nominated", - "AsyncAwait-OnDeck", + "I-compilemem", "I-compiletime", "I-crash", "I-hang", "I-ICE", "I-slow", ] [assign] - -[ping.icebreakers-llvm] -message = """\ -Hey LLVM ICE-breakers! This bug has been identified as a good -"LLVM ICE-breaking candidate". In case it's useful, here are some -[instructions] for tackling these sorts of bugs. Maybe take a look? -Thanks! <3 - -[instructions]: https://rust-lang.github.io/rustc-guide/ice-breaker/llvm.html -""" -label = "ICEBreaker-LLVM" From 37c5e3b561873111efbc5b7530a6ccf69fa754da Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sun, 13 Oct 2019 12:27:11 -0700 Subject: [PATCH 2/2] Return `false` from `needs_drop` for all zero-sized arrays --- src/librustc/ty/util.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index c4d8e452441cb..2588a6cfdb6db 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -1105,6 +1105,9 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx> ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + // Zero-length arrays never contain anything to drop. + ty::Array(_, len) if len.try_eval_usize(tcx, param_env) == Some(0) => false, + // Structural recursion. ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty),

(&mut self, mut predicate: P) -> Option where @@ -3251,6 +3283,40 @@ macro_rules! iterator { Some(next_back_unchecked!(self)) } } + + #[inline] + fn try_rfold(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try + { + // manual unrolling is needed when there are conditional exits from the loop + let mut accum = init; + unsafe { + while len!(self) >= 4 { + accum = f(accum, next_back_unchecked!(self))?; + accum = f(accum, next_back_unchecked!(self))?; + accum = f(accum, next_back_unchecked!(self))?; + accum = f(accum, next_back_unchecked!(self))?; + } + // inlining is_empty everywhere makes a huge performance difference + while !is_empty!(self) { + accum = f(accum, next_back_unchecked!(self))?; + } + } + Try::from_ok(accum) + } + + #[inline] + fn rfold(mut self, init: Acc, mut f: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + // Let LLVM unroll this, rather than using the default + // impl that would force the manual unrolling above + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x); + } + accum + } } #[stable(feature = "fused", since = "1.26.0")] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index f67012d8f2fce..ece61dde490fd 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -176,7 +176,7 @@ Section: Creating a string /// ``` /// fn from_utf8_lossy(mut input: &[u8], mut push: F) where F: FnMut(&str) { /// loop { -/// match std::str::from_utf8(input) { +/// match ::std::str::from_utf8(input) { /// Ok(valid) => { /// push(valid); /// break @@ -184,7 +184,7 @@ Section: Creating a string /// Err(error) => { /// let (valid, after_valid) = input.split_at(error.valid_up_to()); /// unsafe { -/// push(std::str::from_utf8_unchecked(valid)) +/// push(::std::str::from_utf8_unchecked(valid)) /// } /// push("\u{FFFD}"); /// @@ -2167,7 +2167,6 @@ impl str { #[stable(feature = "rust1", since = "1.0.0")] #[inline(always)] // SAFETY: const sound because we transmute two types with the same layout - #[allow(unused_attributes)] #[allow_internal_unstable(const_fn_union)] pub const fn as_bytes(&self) -> &[u8] { #[repr(C)] diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 73d5abf1aed23..c9ccef972c2b5 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -18,11 +18,11 @@ //! //! Each method takes an [`Ordering`] which represents the strength of //! the memory barrier for that operation. These orderings are the -//! same as the [C++20 atomic orderings][1]. For more information see the [nomicon][2]. +//! same as [LLVM atomic orderings][1]. For more information see the [nomicon][2]. //! //! [`Ordering`]: enum.Ordering.html //! -//! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order +//! [1]: https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations //! [2]: ../../../nomicon/atomics.html //! //! Atomic variables are safe to share between threads (they implement [`Sync`]) @@ -113,8 +113,8 @@ //! ``` #![stable(feature = "rust1", since = "1.0.0")] -#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(dead_code))] -#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(unused_imports))] +#![cfg_attr(not(target_has_atomic = "8"), allow(dead_code))] +#![cfg_attr(not(target_has_atomic = "8"), allow(unused_imports))] use self::Ordering::*; @@ -160,14 +160,14 @@ pub fn spin_loop_hint() { /// This type has the same in-memory representation as a [`bool`]. /// /// [`bool`]: ../../../std/primitive.bool.html -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic = "8")] #[stable(feature = "rust1", since = "1.0.0")] #[repr(C, align(1))] pub struct AtomicBool { v: UnsafeCell, } -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic = "8")] #[stable(feature = "rust1", since = "1.0.0")] impl Default for AtomicBool { /// Creates an `AtomicBool` initialized to `false`. @@ -177,14 +177,14 @@ impl Default for AtomicBool { } // Send is implicitly implemented for AtomicBool. -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic = "8")] #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Sync for AtomicBool {} /// A raw pointer type which can be safely shared between threads. /// /// This type has the same in-memory representation as a `*mut T`. -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(target_pointer_width = "16", repr(C, align(2)))] #[cfg_attr(target_pointer_width = "32", repr(C, align(4)))] @@ -193,7 +193,7 @@ pub struct AtomicPtr { p: UnsafeCell<*mut T>, } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] impl Default for AtomicPtr { /// Creates a null `AtomicPtr`. @@ -202,10 +202,10 @@ impl Default for AtomicPtr { } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for AtomicPtr {} -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Sync for AtomicPtr {} @@ -217,8 +217,8 @@ unsafe impl Sync for AtomicPtr {} /// operations synchronize other memory while additionally preserving a total order of such /// operations across all threads. /// -/// Rust's memory orderings are [the same as those of -/// C++20](https://en.cppreference.com/w/cpp/atomic/memory_order). +/// Rust's memory orderings are [the same as +/// LLVM's](https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations). /// /// For more information see the [nomicon]. /// @@ -231,9 +231,9 @@ unsafe impl Sync for AtomicPtr {} pub enum Ordering { /// No ordering constraints, only atomic operations. /// - /// Corresponds to [`memory_order_relaxed`] in C++20. + /// Corresponds to LLVM's [`Monotonic`] ordering. /// - /// [`memory_order_relaxed`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Relaxed_ordering + /// [`Monotonic`]: https://llvm.org/docs/Atomics.html#monotonic #[stable(feature = "rust1", since = "1.0.0")] Relaxed, /// When coupled with a store, all previous operations become ordered @@ -246,12 +246,11 @@ pub enum Ordering { /// /// This ordering is only applicable for operations that can perform a store. /// - /// Corresponds to [`memory_order_release`] in C++20. + /// Corresponds to LLVM's [`Release`] ordering. /// - /// [`Release`]: #variant.Release - /// [`Acquire`]: #variant.Acquire - /// [`Relaxed`]: #variant.Relaxed - /// [`memory_order_release`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering + /// [`Release`]: https://llvm.org/docs/Atomics.html#release + /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire + /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic #[stable(feature = "rust1", since = "1.0.0")] Release, /// When coupled with a load, if the loaded value was written by a store operation with @@ -264,12 +263,11 @@ pub enum Ordering { /// /// This ordering is only applicable for operations that can perform a load. /// - /// Corresponds to [`memory_order_acquire`] in C++20. + /// Corresponds to LLVM's [`Acquire`] ordering. /// - /// [`Acquire`]: #variant.Acquire - /// [`Release`]: #variant.Release - /// [`Relaxed`]: #variant.Relaxed - /// [`memory_order_acquire`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering + /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire + /// [`Release`]: https://llvm.org/docs/Atomics.html#release + /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic #[stable(feature = "rust1", since = "1.0.0")] Acquire, /// Has the effects of both [`Acquire`] and [`Release`] together: @@ -277,28 +275,28 @@ pub enum Ordering { /// /// Notice that in the case of `compare_and_swap`, it is possible that the operation ends up /// not performing any store and hence it has just [`Acquire`] ordering. However, - /// `AcqRel` will never perform [`Relaxed`] accesses. + /// [`AcqRel`][`AcquireRelease`] will never perform [`Relaxed`] accesses. /// /// This ordering is only applicable for operations that combine both loads and stores. /// - /// Corresponds to [`memory_order_acq_rel`] in C++20. + /// Corresponds to LLVM's [`AcquireRelease`] ordering. /// - /// [`memory_order_acq_rel`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering - /// [`Acquire`]: #variant.Acquire - /// [`Release`]: #variant.Release - /// [`Relaxed`]: #variant.Relaxed + /// [`AcquireRelease`]: https://llvm.org/docs/Atomics.html#acquirerelease + /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire + /// [`Release`]: https://llvm.org/docs/Atomics.html#release + /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic #[stable(feature = "rust1", since = "1.0.0")] AcqRel, /// Like [`Acquire`]/[`Release`]/[`AcqRel`] (for load, store, and load-with-store /// operations, respectively) with the additional guarantee that all threads see all /// sequentially consistent operations in the same order. /// - /// Corresponds to [`memory_order_seq_cst`] in C++20. + /// Corresponds to LLVM's [`SequentiallyConsistent`] ordering. /// - /// [`memory_order_seq_cst`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Sequentially-consistent_ordering - /// [`Acquire`]: #variant.Acquire - /// [`Release`]: #variant.Release - /// [`AcqRel`]: #variant.AcqRel + /// [`SequentiallyConsistent`]: https://llvm.org/docs/Atomics.html#sequentiallyconsistent + /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire + /// [`Release`]: https://llvm.org/docs/Atomics.html#release + /// [`AcqRel`]: https://llvm.org/docs/Atomics.html#acquirerelease #[stable(feature = "rust1", since = "1.0.0")] SeqCst, } @@ -306,7 +304,7 @@ pub enum Ordering { /// An [`AtomicBool`] initialized to `false`. /// /// [`AtomicBool`]: struct.AtomicBool.html -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic = "8")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated( since = "1.34.0", @@ -315,7 +313,7 @@ pub enum Ordering { )] pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false); -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic = "8")] impl AtomicBool { /// Creates a new `AtomicBool`. /// @@ -464,7 +462,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "8")] + #[cfg(target_has_atomic = "cas")] pub fn swap(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 } } @@ -502,7 +500,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "8")] + #[cfg(target_has_atomic = "cas")] pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { Ok(x) => x, @@ -553,7 +551,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] - #[cfg(target_has_atomic = "8")] + #[cfg(target_has_atomic = "cas")] pub fn compare_exchange(&self, current: bool, new: bool, @@ -609,7 +607,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] - #[cfg(target_has_atomic = "8")] + #[cfg(target_has_atomic = "cas")] pub fn compare_exchange_weak(&self, current: bool, new: bool, @@ -660,7 +658,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "8")] + #[cfg(target_has_atomic = "cas")] pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_and(self.v.get(), val as u8, order) != 0 } } @@ -702,7 +700,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "8")] + #[cfg(target_has_atomic = "cas")] pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool { // We can't use atomic_nand here because it can result in a bool with // an invalid value. This happens because the atomic operation is done @@ -755,7 +753,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "8")] + #[cfg(target_has_atomic = "cas")] pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_or(self.v.get(), val as u8, order) != 0 } } @@ -796,13 +794,13 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "8")] + #[cfg(target_has_atomic = "cas")] pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 } } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic = "ptr")] impl AtomicPtr { /// Creates a new `AtomicPtr`. /// @@ -953,7 +951,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "ptr")] + #[cfg(target_has_atomic = "cas")] pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T } } @@ -989,7 +987,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "ptr")] + #[cfg(target_has_atomic = "cas")] pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { Ok(x) => x, @@ -1031,7 +1029,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] - #[cfg(target_has_atomic = "ptr")] + #[cfg(target_has_atomic = "cas")] pub fn compare_exchange(&self, current: *mut T, new: *mut T, @@ -1091,7 +1089,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] - #[cfg(target_has_atomic = "ptr")] + #[cfg(target_has_atomic = "cas")] pub fn compare_exchange_weak(&self, current: *mut T, new: *mut T, @@ -1112,7 +1110,7 @@ impl AtomicPtr { } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic = "8")] #[stable(feature = "atomic_bool_from", since = "1.24.0")] impl From for AtomicBool { /// Converts a `bool` into an `AtomicBool`. @@ -1128,17 +1126,16 @@ impl From for AtomicBool { fn from(b: bool) -> Self { Self::new(b) } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "atomic_from", since = "1.23.0")] impl From<*mut T> for AtomicPtr { #[inline] fn from(p: *mut T) -> Self { Self::new(p) } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic = "ptr")] macro_rules! atomic_int { - ($cfg_cas:meta, - $stable:meta, + ($stable:meta, $stable_cxchg:meta, $stable_debug:meta, $stable_access:meta, @@ -1359,7 +1356,7 @@ assert_eq!(some_var.swap(10, Ordering::Relaxed), 5); ```"), #[inline] #[$stable] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_swap(self.v.get(), val, order) } } @@ -1399,7 +1396,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10); ```"), #[inline] #[$stable] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn compare_and_swap(&self, current: $int_type, new: $int_type, @@ -1457,7 +1454,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10); ```"), #[inline] #[$stable_cxchg] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn compare_exchange(&self, current: $int_type, new: $int_type, @@ -1509,7 +1506,7 @@ loop { ```"), #[inline] #[$stable_cxchg] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn compare_exchange_weak(&self, current: $int_type, new: $int_type, @@ -1547,7 +1544,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 10); ```"), #[inline] #[$stable] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_add(self.v.get(), val, order) } } @@ -1579,7 +1576,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 10); ```"), #[inline] #[$stable] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_sub(self.v.get(), val, order) } } @@ -1614,7 +1611,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b100001); ```"), #[inline] #[$stable] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_and(self.v.get(), val, order) } } @@ -1650,7 +1647,7 @@ assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31)); ```"), #[inline] #[$stable_nand] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_nand(self.v.get(), val, order) } } @@ -1685,7 +1682,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b111111); ```"), #[inline] #[$stable] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_or(self.v.get(), val, order) } } @@ -1720,7 +1717,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b011110); ```"), #[inline] #[$stable] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_xor(self.v.get(), val, order) } } @@ -1770,7 +1767,7 @@ assert_eq!(x.load(Ordering::SeqCst), 9); #[unstable(feature = "no_more_cas", reason = "no more CAS loops in user code", issue = "48655")] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn fetch_update(&self, mut f: F, fetch_order: Ordering, @@ -1831,7 +1828,7 @@ assert!(max_foo == 42); #[unstable(feature = "atomic_min_max", reason = "easier and faster min/max than writing manual CAS loop", issue = "48655")] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { $max_fn(self.v.get(), val, order) } } @@ -1883,7 +1880,7 @@ assert_eq!(min_foo, 12); #[unstable(feature = "atomic_min_max", reason = "easier and faster min/max than writing manual CAS loop", issue = "48655")] - #[$cfg_cas] + #[cfg(target_has_atomic = "cas")] pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { $min_fn(self.v.get(), val, order) } } @@ -1893,9 +1890,8 @@ assert_eq!(min_foo, 12); } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic = "8")] atomic_int! { - cfg(target_has_atomic = "8"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1910,9 +1906,8 @@ atomic_int! { "AtomicI8::new(0)", i8 AtomicI8 ATOMIC_I8_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic = "8")] atomic_int! { - cfg(target_has_atomic = "8"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1927,9 +1922,8 @@ atomic_int! { "AtomicU8::new(0)", u8 AtomicU8 ATOMIC_U8_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "16"))] +#[cfg(target_has_atomic = "16")] atomic_int! { - cfg(target_has_atomic = "16"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1944,9 +1938,8 @@ atomic_int! { "AtomicI16::new(0)", i16 AtomicI16 ATOMIC_I16_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "16"))] +#[cfg(target_has_atomic = "16")] atomic_int! { - cfg(target_has_atomic = "16"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1961,9 +1954,8 @@ atomic_int! { "AtomicU16::new(0)", u16 AtomicU16 ATOMIC_U16_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "32"))] +#[cfg(target_has_atomic = "32")] atomic_int! { - cfg(target_has_atomic = "32"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1978,9 +1970,8 @@ atomic_int! { "AtomicI32::new(0)", i32 AtomicI32 ATOMIC_I32_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "32"))] +#[cfg(target_has_atomic = "32")] atomic_int! { - cfg(target_has_atomic = "32"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1995,12 +1986,8 @@ atomic_int! { "AtomicU32::new(0)", u32 AtomicU32 ATOMIC_U32_INIT } -#[cfg(any( - all(bootstrap, target_has_atomic = "64"), - target_has_atomic_load_store = "64" -))] +#[cfg(target_has_atomic = "64")] atomic_int! { - cfg(target_has_atomic = "64"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -2015,12 +2002,8 @@ atomic_int! { "AtomicI64::new(0)", i64 AtomicI64 ATOMIC_I64_INIT } -#[cfg(any( - all(bootstrap, target_has_atomic = "64"), - target_has_atomic_load_store = "64" -))] +#[cfg(target_has_atomic = "64")] atomic_int! { - cfg(target_has_atomic = "64"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -2035,9 +2018,8 @@ atomic_int! { "AtomicU64::new(0)", u64 AtomicU64 ATOMIC_U64_INIT } -#[cfg(target_has_atomic_load_store = "128")] +#[cfg(target_has_atomic = "128")] atomic_int! { - cfg(target_has_atomic = "128"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), @@ -2052,9 +2034,8 @@ atomic_int! { "AtomicI128::new(0)", i128 AtomicI128 ATOMIC_I128_INIT } -#[cfg(target_has_atomic_load_store = "128")] +#[cfg(target_has_atomic = "128")] atomic_int! { - cfg(target_has_atomic = "128"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), @@ -2069,24 +2050,20 @@ atomic_int! { "AtomicU128::new(0)", u128 AtomicU128 ATOMIC_U128_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[cfg(target_pointer_width = "16")] macro_rules! ptr_width { () => { 2 } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[cfg(target_pointer_width = "32")] macro_rules! ptr_width { () => { 4 } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[cfg(target_pointer_width = "64")] macro_rules! ptr_width { () => { 8 } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic = "ptr")] atomic_int!{ - cfg(target_has_atomic = "ptr"), stable(feature = "rust1", since = "1.0.0"), stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), @@ -2101,9 +2078,8 @@ atomic_int!{ "AtomicIsize::new(0)", isize AtomicIsize ATOMIC_ISIZE_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic = "ptr")] atomic_int!{ - cfg(target_has_atomic = "ptr"), stable(feature = "rust1", since = "1.0.0"), stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), @@ -2120,7 +2096,7 @@ atomic_int!{ } #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] fn strongest_failure_ordering(order: Ordering) -> Ordering { match order { Release => Relaxed, @@ -2154,7 +2130,7 @@ unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { } #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xchg_acq(dst, val), @@ -2167,7 +2143,7 @@ unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { /// Returns the previous value (like __sync_fetch_and_add). #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xadd_acq(dst, val), @@ -2180,7 +2156,7 @@ unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { /// Returns the previous value (like __sync_fetch_and_sub). #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xsub_acq(dst, val), @@ -2192,7 +2168,7 @@ unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_compare_exchange(dst: *mut T, old: T, new: T, @@ -2217,7 +2193,7 @@ unsafe fn atomic_compare_exchange(dst: *mut T, } #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_compare_exchange_weak(dst: *mut T, old: T, new: T, @@ -2242,7 +2218,7 @@ unsafe fn atomic_compare_exchange_weak(dst: *mut T, } #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_and_acq(dst, val), @@ -2254,7 +2230,7 @@ unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_nand_acq(dst, val), @@ -2266,7 +2242,7 @@ unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_or_acq(dst, val), @@ -2278,7 +2254,7 @@ unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xor_acq(dst, val), @@ -2291,7 +2267,7 @@ unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { /// returns the max value (signed comparison) #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_max_acq(dst, val), @@ -2304,7 +2280,7 @@ unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { /// returns the min value (signed comparison) #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_min_acq(dst, val), @@ -2317,7 +2293,7 @@ unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { /// returns the max value (signed comparison) #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_umax_acq(dst, val), @@ -2330,7 +2306,7 @@ unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { /// returns the min value (signed comparison) #[inline] -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_umin_acq(dst, val), @@ -2528,7 +2504,7 @@ pub fn compiler_fence(order: Ordering) { } -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic = "8")] #[stable(feature = "atomic_debug", since = "1.3.0")] impl fmt::Debug for AtomicBool { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -2536,7 +2512,7 @@ impl fmt::Debug for AtomicBool { } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "atomic_debug", since = "1.3.0")] impl fmt::Debug for AtomicPtr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -2544,7 +2520,7 @@ impl fmt::Debug for AtomicPtr { } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "atomic_pointer", since = "1.24.0")] impl fmt::Pointer for AtomicPtr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index 6f841bd2adf41..65e293642874c 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -217,7 +217,7 @@ impl fmt::Debug for Context<'_> { /// This handle encapsulates a [`RawWaker`] instance, which defines the /// executor-specific wakeup behavior. /// -/// Implements [`Clone`], [`Send`], and [`Sync`]. +/// Implements [`Clone`], [`trait@Send`], and [`trait@Sync`]. /// /// [`RawWaker`]: struct.RawWaker.html #[repr(transparent)] diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs index 4f3b79c78b66c..9e133ac568811 100644 --- a/src/libcore/tests/array.rs +++ b/src/libcore/tests/array.rs @@ -1,4 +1,4 @@ -use core::array::{FixedSizeArray, IntoIter}; +use core::array::FixedSizeArray; use core::convert::TryFrom; #[test] @@ -40,208 +40,3 @@ fn array_try_from() { 30 31 32 } } - - -#[test] -fn iterator_collect() { - let arr = [0, 1, 2, 5, 9]; - let v: Vec<_> = IntoIter::new(arr.clone()).collect(); - assert_eq!(&arr[..], &v[..]); -} - -#[test] -fn iterator_rev_collect() { - let arr = [0, 1, 2, 5, 9]; - let v: Vec<_> = IntoIter::new(arr.clone()).rev().collect(); - assert_eq!(&v[..], &[9, 5, 2, 1, 0]); -} - -#[test] -fn iterator_nth() { - let v = [0, 1, 2, 3, 4]; - for i in 0..v.len() { - assert_eq!(IntoIter::new(v.clone()).nth(i).unwrap(), v[i]); - } - assert_eq!(IntoIter::new(v.clone()).nth(v.len()), None); - - let mut iter = IntoIter::new(v); - assert_eq!(iter.nth(2).unwrap(), v[2]); - assert_eq!(iter.nth(1).unwrap(), v[4]); -} - -#[test] -fn iterator_last() { - let v = [0, 1, 2, 3, 4]; - assert_eq!(IntoIter::new(v).last().unwrap(), 4); - assert_eq!(IntoIter::new([0]).last().unwrap(), 0); - - let mut it = IntoIter::new([0, 9, 2, 4]); - assert_eq!(it.next_back(), Some(4)); - assert_eq!(it.last(), Some(2)); -} - -#[test] -fn iterator_clone() { - let mut it = IntoIter::new([0, 2, 4, 6, 8]); - assert_eq!(it.next(), Some(0)); - assert_eq!(it.next_back(), Some(8)); - let mut clone = it.clone(); - assert_eq!(it.next_back(), Some(6)); - assert_eq!(clone.next_back(), Some(6)); - assert_eq!(it.next_back(), Some(4)); - assert_eq!(clone.next_back(), Some(4)); - assert_eq!(it.next(), Some(2)); - assert_eq!(clone.next(), Some(2)); -} - -#[test] -fn iterator_fused() { - let mut it = IntoIter::new([0, 9, 2]); - assert_eq!(it.next(), Some(0)); - assert_eq!(it.next(), Some(9)); - assert_eq!(it.next(), Some(2)); - assert_eq!(it.next(), None); - assert_eq!(it.next(), None); - assert_eq!(it.next(), None); - assert_eq!(it.next(), None); - assert_eq!(it.next(), None); -} - -#[test] -fn iterator_len() { - let mut it = IntoIter::new([0, 1, 2, 5, 9]); - assert_eq!(it.size_hint(), (5, Some(5))); - assert_eq!(it.len(), 5); - assert_eq!(it.is_empty(), false); - - assert_eq!(it.next(), Some(0)); - assert_eq!(it.size_hint(), (4, Some(4))); - assert_eq!(it.len(), 4); - assert_eq!(it.is_empty(), false); - - assert_eq!(it.next_back(), Some(9)); - assert_eq!(it.size_hint(), (3, Some(3))); - assert_eq!(it.len(), 3); - assert_eq!(it.is_empty(), false); - - // Empty - let it = IntoIter::new([] as [String; 0]); - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.len(), 0); - assert_eq!(it.is_empty(), true); -} - -#[test] -fn iterator_count() { - let v = [0, 1, 2, 3, 4]; - assert_eq!(IntoIter::new(v.clone()).count(), 5); - - let mut iter2 = IntoIter::new(v); - iter2.next(); - iter2.next(); - assert_eq!(iter2.count(), 3); -} - -#[test] -fn iterator_flat_map() { - assert!((0..5).flat_map(|i| IntoIter::new([2 * i, 2 * i + 1])).eq(0..10)); -} - -#[test] -fn iterator_debug() { - let arr = [0, 1, 2, 5, 9]; - assert_eq!( - format!("{:?}", IntoIter::new(arr)), - "IntoIter([0, 1, 2, 5, 9])", - ); -} - -#[test] -fn iterator_drops() { - use core::cell::Cell; - - // This test makes sure the correct number of elements are dropped. The `R` - // type is just a reference to a `Cell` that is incremented when an `R` is - // dropped. - - #[derive(Clone)] - struct Foo<'a>(&'a Cell); - - impl Drop for Foo<'_> { - fn drop(&mut self) { - self.0.set(self.0.get() + 1); - } - } - - fn five(i: &Cell) -> [Foo<'_>; 5] { - // This is somewhat verbose because `Foo` does not implement `Copy` - // since it implements `Drop`. Consequently, we cannot write - // `[Foo(i); 5]`. - [Foo(i), Foo(i), Foo(i), Foo(i), Foo(i)] - } - - // Simple: drop new iterator. - let i = Cell::new(0); - { - IntoIter::new(five(&i)); - } - assert_eq!(i.get(), 5); - - // Call `next()` once. - let i = Cell::new(0); - { - let mut iter = IntoIter::new(five(&i)); - let _x = iter.next(); - assert_eq!(i.get(), 0); - assert_eq!(iter.count(), 4); - assert_eq!(i.get(), 4); - } - assert_eq!(i.get(), 5); - - // Check `clone` and calling `next`/`next_back`. - let i = Cell::new(0); - { - let mut iter = IntoIter::new(five(&i)); - iter.next(); - assert_eq!(i.get(), 1); - iter.next_back(); - assert_eq!(i.get(), 2); - - let mut clone = iter.clone(); - assert_eq!(i.get(), 2); - - iter.next(); - assert_eq!(i.get(), 3); - - clone.next(); - assert_eq!(i.get(), 4); - - assert_eq!(clone.count(), 2); - assert_eq!(i.get(), 6); - } - assert_eq!(i.get(), 8); - - // Check via `nth`. - let i = Cell::new(0); - { - let mut iter = IntoIter::new(five(&i)); - let _x = iter.nth(2); - assert_eq!(i.get(), 2); - let _y = iter.last(); - assert_eq!(i.get(), 3); - } - assert_eq!(i.get(), 5); - - // Check every element. - let i = Cell::new(0); - for (index, _x) in IntoIter::new(five(&i)).enumerate() { - assert_eq!(i.get(), index); - } - assert_eq!(i.get(), 5); - - let i = Cell::new(0); - for (index, _x) in IntoIter::new(five(&i)).rev().enumerate() { - assert_eq!(i.get(), index); - } - assert_eq!(i.get(), 5); -} diff --git a/src/libcore/tests/fmt/builders.rs b/src/libcore/tests/fmt/builders.rs index 255724432816d..200659b91bb4e 100644 --- a/src/libcore/tests/fmt/builders.rs +++ b/src/libcore/tests/fmt/builders.rs @@ -319,46 +319,6 @@ mod debug_map { format!("{:#?}", Bar)); } - #[test] - fn test_entry_err() { - // Ensure errors in a map entry don't trigger panics (#65231) - use std::fmt::Write; - - struct ErrorFmt; - - impl fmt::Debug for ErrorFmt { - fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { - Err(fmt::Error) - } - } - - struct KeyValue(usize, K, V); - - impl fmt::Debug for KeyValue - where - K: fmt::Debug, - V: fmt::Debug, - { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut map = fmt.debug_map(); - - for _ in 0..self.0 { - map.entry(&self.1, &self.2); - } - - map.finish() - } - } - - let mut buf = String::new(); - - assert!(write!(&mut buf, "{:?}", KeyValue(1, ErrorFmt, "bar")).is_err()); - assert!(write!(&mut buf, "{:?}", KeyValue(1, "foo", ErrorFmt)).is_err()); - - assert!(write!(&mut buf, "{:?}", KeyValue(2, ErrorFmt, "bar")).is_err()); - assert!(write!(&mut buf, "{:?}", KeyValue(2, "foo", ErrorFmt)).is_err()); - } - #[test] #[should_panic] fn test_invalid_key_when_entry_is_incomplete() { diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index b28ed2eaa0876..35661356028cb 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -31,7 +31,6 @@ #![feature(slice_partition_dedup)] #![feature(int_error_matching)] #![feature(const_fn)] -#![feature(array_value_iter)] #![feature(iter_partition_in_place)] #![feature(iter_is_partitioned)] #![feature(iter_order_by)] diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index d22420e76dcd4..f9c1be20b8bc1 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -410,7 +410,7 @@ impl<'a> Parser<'a> { &self.input[start..self.input.len()] } - /// Parses an `Argument` structure, or what's contained within braces inside the format string. + /// Parses an Argument structure, or what's contained within braces inside the format string fn argument(&mut self) -> Argument<'a> { let pos = self.position(); let format = self.format(); @@ -464,7 +464,7 @@ impl<'a> Parser<'a> { } /// Parses a format specifier at the current position, returning all of the - /// relevant information in the `FormatSpec` struct. + /// relevant information in the FormatSpec struct. fn format(&mut self) -> FormatSpec<'a> { let mut spec = FormatSpec { fill: None, @@ -571,7 +571,7 @@ impl<'a> Parser<'a> { spec } - /// Parses a `Count` parameter at the current position. This does not check + /// Parses a Count parameter at the current position. This does not check /// for 'CountIsNextParam' because that is only used in precision, not /// width. fn count(&mut self, start: usize) -> (Count, Option) { diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index a35847c85fc20..236ed15050571 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -156,21 +156,21 @@ unsafe extern "C" fn rust_eh_personality(version: c_int, if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { match eh_action { EHAction::None | - EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND, - EHAction::Catch(_) => uw::_URC_HANDLER_FOUND, - EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR, + EHAction::Cleanup(_) => return uw::_URC_CONTINUE_UNWIND, + EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND, + EHAction::Terminate => return uw::_URC_FATAL_PHASE1_ERROR, } } else { match eh_action { - EHAction::None => uw::_URC_CONTINUE_UNWIND, + EHAction::None => return uw::_URC_CONTINUE_UNWIND, EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => { uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t); uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0); uw::_Unwind_SetIP(context, lpad); - uw::_URC_INSTALL_CONTEXT + return uw::_URC_INSTALL_CONTEXT; } - EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR, + EHAction::Terminate => return uw::_URC_FATAL_PHASE2_ERROR, } } } diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs index 16b699a443799..457ffcd34f9c7 100644 --- a/src/libpanic_unwind/seh64_gnu.rs +++ b/src/libpanic_unwind/seh64_gnu.rs @@ -46,7 +46,7 @@ pub fn payload() -> *mut u8 { pub unsafe fn cleanup(ptr: *mut u8) -> Box { let panic_ctx = Box::from_raw(ptr as *mut PanicData); - panic_ctx.data + return panic_ctx.data; } // SEH doesn't support resuming unwinds after calling a landing pad like diff --git a/src/libproc_macro/bridge/mod.rs b/src/libproc_macro/bridge/mod.rs index c26b59f473c36..3c48466fffa28 100644 --- a/src/libproc_macro/bridge/mod.rs +++ b/src/libproc_macro/bridge/mod.rs @@ -148,7 +148,6 @@ macro_rules! with_api { fn debug($self: $S::Span) -> String; fn def_site() -> $S::Span; fn call_site() -> $S::Span; - fn mixed_site() -> $S::Span; fn source_file($self: $S::Span) -> $S::SourceFile; fn parent($self: $S::Span) -> Option<$S::Span>; fn source($self: $S::Span) -> $S::Span; diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 6166561d87f15..d5cdc266acb6a 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -25,7 +25,8 @@ #![feature(extern_types)] #![feature(in_band_lifetimes)] #![feature(optin_builtin_traits)] -#![cfg_attr(bootstrap, feature(non_exhaustive))] +#![feature(mem_take)] +#![feature(non_exhaustive)] #![feature(rustc_attrs)] #![feature(specialization)] @@ -270,15 +271,6 @@ impl Span { Span(bridge::client::Span::call_site()) } - /// A span that represents `macro_rules` hygiene, and sometimes resolves at the macro - /// definition site (local variables, labels, `$crate`) and sometimes at the macro - /// call site (everything else). - /// The span location is taken from the call-site. - #[unstable(feature = "proc_macro_mixed_site", issue = "65049")] - pub fn mixed_site() -> Span { - Span(bridge::client::Span::mixed_site()) - } - /// The original source file into which this span points. #[unstable(feature = "proc_macro_span", issue = "54725")] pub fn source_file(&self) -> SourceFile { diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 93274ef0c927c..0834faf132424 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -18,23 +18,21 @@ jobserver = "0.1" num_cpus = "1.0" scoped-tls = "1.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } -rustc-rayon = "0.3.0" -rustc-rayon-core = "0.3.0" +rustc-rayon = "0.2.0" +rustc-rayon-core = "0.2.0" polonius-engine = "0.10.0" rustc_apfloat = { path = "../librustc_apfloat" } rustc_target = { path = "../librustc_target" } rustc_macros = { path = "../librustc_macros" } rustc_data_structures = { path = "../librustc_data_structures" } -rustc_index = { path = "../librustc_index" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } -syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } backtrace = "0.3.3" 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.8", features = ["union", "may_dangle"] } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } measureme = "0.3" diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 3daf0fc9df7a0..5d06f62f44616 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -26,12 +26,12 @@ macro_rules! arena_types { [] steal_mir: rustc::ty::steal::Steal>, [] mir: rustc::mir::Body<$tcx>, [] steal_promoted: rustc::ty::steal::Steal< - rustc_index::vec::IndexVec< + rustc_data_structures::indexed_vec::IndexVec< rustc::mir::Promoted, rustc::mir::Body<$tcx> > >, - [] promoted: rustc_index::vec::IndexVec< + [] promoted: rustc_data_structures::indexed_vec::IndexVec< rustc::mir::Promoted, rustc::mir::Body<$tcx> >, @@ -45,7 +45,7 @@ macro_rules! arena_types { [decode] specialization_graph: rustc::traits::specialization_graph::Graph, [] region_scope_tree: rustc::middle::region::ScopeTree, [] item_local_set: rustc::util::nodemap::ItemLocalSet, - [decode] mir_const_qualif: rustc_index::bit_set::BitSet, + [decode] mir_const_qualif: rustc_data_structures::bit_set::BitSet, [] trait_impls_of: rustc::ty::trait_def::TraitImpls, [] dropck_outlives: rustc::infer::canonical::Canonical<'tcx, @@ -98,6 +98,7 @@ macro_rules! arena_types { 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, [few] stability_index: rustc::middle::stability::Index<'tcx>, [few] features: syntax::feature_gate::Features, diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index dea8d70aaf4e6..3d5e7dd0af121 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -59,7 +59,7 @@ use crate::ich::{Fingerprint, StableHashingContext}; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use std::fmt; use std::hash::Hash; -use syntax_pos::symbol::Symbol; +use syntax_pos::symbol::InternedString; use crate::traits; use crate::traits::query::{ CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, @@ -114,6 +114,7 @@ macro_rules! define_dep_nodes { impl DepKind { #[allow(unreachable_code)] + #[inline] pub fn can_reconstruct_query_key<$tcx>(&self) -> bool { match *self { $( @@ -149,6 +150,7 @@ macro_rules! define_dep_nodes { } } + #[inline(always)] pub fn is_eval_always(&self) -> bool { match *self { $( @@ -197,6 +199,7 @@ macro_rules! define_dep_nodes { impl DepNode { #[allow(unreachable_code, non_snake_case)] + #[inline(always)] pub fn new<'tcx>(tcx: TyCtxt<'tcx>, dep: DepConstructor<'tcx>) -> DepNode @@ -216,16 +219,14 @@ macro_rules! define_dep_nodes { hash }; - #[cfg(debug_assertions)] + if cfg!(debug_assertions) && + !dep_node.kind.can_reconstruct_query_key() && + (tcx.sess.opts.debugging_opts.incremental_info || + tcx.sess.opts.debugging_opts.query_dep_graph) { - if !dep_node.kind.can_reconstruct_query_key() && - (tcx.sess.opts.debugging_opts.incremental_info || - tcx.sess.opts.debugging_opts.query_dep_graph) - { - tcx.dep_graph.register_dep_node_debug_str(dep_node, || { - arg.to_debug_str(tcx) - }); - } + tcx.dep_graph.register_dep_node_debug_str(dep_node, || { + arg.to_debug_str(tcx) + }); } return dep_node; @@ -241,16 +242,14 @@ macro_rules! define_dep_nodes { hash }; - #[cfg(debug_assertions)] + if cfg!(debug_assertions) && + !dep_node.kind.can_reconstruct_query_key() && + (tcx.sess.opts.debugging_opts.incremental_info || + tcx.sess.opts.debugging_opts.query_dep_graph) { - if !dep_node.kind.can_reconstruct_query_key() && - (tcx.sess.opts.debugging_opts.incremental_info || - tcx.sess.opts.debugging_opts.query_dep_graph) - { - tcx.dep_graph.register_dep_node_debug_str(dep_node, || { - tupled_args.to_debug_str(tcx) - }); - } + tcx.dep_graph.register_dep_node_debug_str(dep_node, || { + tupled_args.to_debug_str(tcx) + }); } return dep_node; @@ -268,6 +267,7 @@ macro_rules! define_dep_nodes { /// Construct a DepNode from the given DepKind and DefPathHash. This /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. + #[inline(always)] pub fn from_def_path_hash(kind: DepKind, def_path_hash: DefPathHash) -> DepNode { @@ -281,6 +281,7 @@ macro_rules! define_dep_nodes { /// Creates a new, parameterless DepNode. This method will assert /// that the DepNode corresponding to the given DepKind actually /// does not require any parameters. + #[inline(always)] pub fn new_no_params(kind: DepKind) -> DepNode { debug_assert!(!kind.has_params()); DepNode { @@ -299,6 +300,7 @@ macro_rules! define_dep_nodes { /// DepNode. Condition (2) might not be fulfilled if a DepNode /// refers to something from the previous compilation session that /// has been removed. + #[inline] pub fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option { if self.kind.can_reconstruct_query_key() { let def_path_hash = DefPathHash(self.hash); @@ -384,12 +386,14 @@ impl fmt::Debug for DepNode { impl DefPathHash { + #[inline(always)] pub fn to_dep_node(self, kind: DepKind) -> DepNode { DepNode::from_def_path_hash(kind, self) } } impl DefId { + #[inline(always)] pub fn to_dep_node(self, tcx: TyCtxt<'_>, kind: DepKind) -> DepNode { DepNode::from_def_path_hash(kind, tcx.def_path_hash(self)) } @@ -426,7 +430,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [anon] TraitSelect, - [] CompileCodegenUnit(Symbol), + [] CompileCodegenUnit(InternedString), [eval_always] Analysis(CrateNum), ]); diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 0104507f7020f..acfdc91523f70 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -1,16 +1,15 @@ use errors::Diagnostic; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use smallvec::SmallVec; -use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, AtomicU64, Ordering}; -use rustc_data_structures::sharded::{self, Sharded}; -use std::sync::atomic::Ordering::SeqCst; +use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, Ordering}; use std::env; use std::hash::Hash; use std::collections::hash_map::Entry; use std::mem; use crate::ty::{self, TyCtxt}; +use crate::util::common::{ProfileQueriesMsg, profq_msg}; use parking_lot::{Mutex, Condvar}; use crate::ich::{StableHashingContext, StableHashingContextProvider, Fingerprint}; @@ -27,15 +26,15 @@ pub struct DepGraph { data: Option>, } -rustc_index::newtype_index! { +newtype_index! { pub struct DepNodeIndex { .. } } impl DepNodeIndex { - pub const INVALID: DepNodeIndex = DepNodeIndex::MAX; + const INVALID: DepNodeIndex = DepNodeIndex::MAX; } -#[derive(PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum DepNodeColor { Red, Green(DepNodeIndex) @@ -55,7 +54,7 @@ struct DepGraphData { /// tracking. The `current` field is the dependency graph of only the /// current compilation session: We don't merge the previous dep-graph into /// current one anymore. - current: CurrentDepGraph, + current: Lock, /// The dep-graph from the previous compilation session. It contains all /// nodes and edges as well as all fingerprints of nodes that have them. @@ -76,6 +75,9 @@ struct DepGraphData { previous_work_products: FxHashMap, dep_node_debug: Lock>, + + // Used for testing, only populated when -Zquery-dep-graph is specified. + loaded_from_cache: Lock>, } pub fn hash_result(hcx: &mut StableHashingContext<'_>, result: &R) -> Option @@ -97,11 +99,12 @@ impl DepGraph { data: Some(Lrc::new(DepGraphData { previous_work_products: prev_work_products, dep_node_debug: Default::default(), - current: CurrentDepGraph::new(prev_graph_node_count), + current: Lock::new(CurrentDepGraph::new(prev_graph_node_count)), emitting_diagnostics: Default::default(), emitting_diagnostics_cond_var: Condvar::new(), previous: prev_graph, colors: DepNodeColorMap::new(prev_graph_node_count), + loaded_from_cache: Default::default(), })), } } @@ -119,12 +122,13 @@ impl DepGraph { } pub fn query(&self) -> DepGraphQuery { - let data = self.data.as_ref().unwrap().current.data.lock(); - let nodes: Vec<_> = data.iter().map(|n| n.node).collect(); + let current_dep_graph = self.data.as_ref().unwrap().current.borrow(); + let nodes: Vec<_> = current_dep_graph.data.iter().map(|n| n.node).collect(); let mut edges = Vec::new(); - for (from, edge_targets) in data.iter().map(|d| (d.node, &d.edges)) { + for (from, edge_targets) in current_dep_graph.data.iter() + .map(|d| (d.node, &d.edges)) { for &edge_target in edge_targets.iter() { - let to = data[edge_target].node; + let to = current_dep_graph.data[edge_target].node; edges.push((from, to)); } } @@ -203,7 +207,7 @@ impl DepGraph { read_set: Default::default(), }), |data, key, fingerprint, task| { - data.complete_task(key, task.unwrap(), fingerprint) + data.borrow_mut().complete_task(key, task.unwrap(), fingerprint) }, hash_result) } @@ -224,7 +228,7 @@ impl DepGraph { self.with_task_impl(key, cx, input, true, identity_fn, |_| None, |data, key, fingerprint, _| { - data.alloc_node(key, SmallVec::new(), fingerprint) + data.borrow_mut().alloc_node(key, SmallVec::new(), fingerprint) }, hash_result::) } @@ -237,7 +241,7 @@ impl DepGraph { no_tcx: bool, task: fn(C, A) -> R, create_task: fn(DepNode) -> Option, - finish_task_and_alloc_depnode: fn(&CurrentDepGraph, + finish_task_and_alloc_depnode: fn(&Lock, DepNode, Fingerprint, Option) -> DepNodeIndex, @@ -256,6 +260,10 @@ impl DepGraph { // - we can get an idea of the runtime cost. let mut hcx = cx.get_stable_hashing_context(); + if cfg!(debug_assertions) { + profq_msg(hcx.sess(), ProfileQueriesMsg::TaskBegin(key.clone())) + }; + let result = if no_tcx { task(cx, arg) } else { @@ -271,6 +279,10 @@ impl DepGraph { }) }; + if cfg!(debug_assertions) { + profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd) + }; + let current_fingerprint = hash_result(&mut hcx, &result); let dep_node_index = finish_task_and_alloc_depnode( @@ -351,6 +363,7 @@ impl DepGraph { (r, task_deps.into_inner()) }); let dep_node_index = data.current + .borrow_mut() .complete_anon_task(dep_kind, task_deps); (result, dep_node_index) } else { @@ -374,7 +387,8 @@ impl DepGraph { self.with_task_impl(key, cx, arg, false, task, |_| None, |data, key, fingerprint, _| { - data.alloc_node(key, smallvec![], fingerprint) + let mut current = data.borrow_mut(); + current.alloc_node(key, smallvec![], fingerprint) }, hash_result) } @@ -382,9 +396,9 @@ impl DepGraph { #[inline] pub fn read(&self, v: DepNode) { if let Some(ref data) = self.data { - let map = data.current.node_to_node_index.get_shard_by_value(&v).lock(); - if let Some(dep_node_index) = map.get(&v).copied() { - std::mem::drop(map); + let current = data.current.borrow_mut(); + if let Some(&dep_node_index) = current.node_to_node_index.get(&v) { + std::mem::drop(current); data.read_index(dep_node_index); } else { bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind) @@ -405,9 +419,8 @@ impl DepGraph { .as_ref() .unwrap() .current + .borrow_mut() .node_to_node_index - .get_shard_by_value(dep_node) - .lock() .get(dep_node) .cloned() .unwrap() @@ -416,11 +429,7 @@ impl DepGraph { #[inline] pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { if let Some(ref data) = self.data { - data.current - .node_to_node_index - .get_shard_by_value(&dep_node) - .lock() - .contains_key(dep_node) + data.current.borrow_mut().node_to_node_index.contains_key(dep_node) } else { false } @@ -428,8 +437,8 @@ impl DepGraph { #[inline] pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint { - let data = self.data.as_ref().expect("dep graph enabled").current.data.lock(); - data[dep_node_index].fingerprint + let current = self.data.as_ref().expect("dep graph enabled").current.borrow_mut(); + current.data[dep_node_index].fingerprint } pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option { @@ -483,29 +492,32 @@ impl DepGraph { pub fn edge_deduplication_data(&self) -> Option<(u64, u64)> { if cfg!(debug_assertions) { - let current_dep_graph = &self.data.as_ref().unwrap().current; + let current_dep_graph = self.data.as_ref().unwrap().current.borrow(); - Some((current_dep_graph.total_read_count.load(SeqCst), - current_dep_graph.total_duplicate_read_count.load(SeqCst))) + Some((current_dep_graph.total_read_count, + current_dep_graph.total_duplicate_read_count)) } else { None } } pub fn serialize(&self) -> SerializedDepGraph { - let data = self.data.as_ref().unwrap().current.data.lock(); + let current_dep_graph = self.data.as_ref().unwrap().current.borrow(); let fingerprints: IndexVec = - data.iter().map(|d| d.fingerprint).collect(); + current_dep_graph.data.iter().map(|d| d.fingerprint).collect(); let nodes: IndexVec = - data.iter().map(|d| d.node).collect(); + current_dep_graph.data.iter().map(|d| d.node).collect(); - let total_edge_count: usize = data.iter().map(|d| d.edges.len()).sum(); + let total_edge_count: usize = current_dep_graph.data.iter() + .map(|d| d.edges.len()) + .sum(); let mut edge_list_indices = IndexVec::with_capacity(nodes.len()); let mut edge_list_data = Vec::with_capacity(total_edge_count); - for (current_dep_node_index, edges) in data.iter_enumerated().map(|(i, d)| (i, &d.edges)) { + for (current_dep_node_index, edges) in current_dep_graph.data.iter_enumerated() + .map(|(i, d)| (i, &d.edges)) { let start = edge_list_data.len() as u32; // This should really just be a memcpy :/ edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex::new(i.index()))); @@ -601,11 +613,7 @@ impl DepGraph { #[cfg(not(parallel_compiler))] { - debug_assert!(!data.current - .node_to_node_index - .get_shard_by_value(dep_node) - .lock() - .contains_key(dep_node)); + debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node)); debug_assert!(data.colors.get(prev_dep_node_index).is_none()); } @@ -738,13 +746,15 @@ impl DepGraph { // There may be multiple threads trying to mark the same dep node green concurrently let dep_node_index = { + let mut current = data.current.borrow_mut(); + // Copy the fingerprint from the previous graph, // so we don't have to recompute it let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index); // We allocating an entry for the node in the current dependency graph and // adding all the appropriate edges imported from the previous graph - data.current.intern_node(*dep_node, current_deps, fingerprint) + current.intern_node(*dep_node, current_deps, fingerprint) }; // ... emitting any stored diagnostic ... @@ -848,8 +858,6 @@ impl DepGraph { // This method will only load queries that will end up in the disk cache. // Other queries will not be executed. pub fn exec_cache_promotions(&self, tcx: TyCtxt<'_>) { - let _prof_timer = tcx.prof.generic_activity("incr_comp_query_cache_promotion"); - let data = self.data.as_ref().unwrap(); for prev_index in data.colors.values.indices() { match data.colors.get(prev_index) { @@ -866,6 +874,25 @@ impl DepGraph { } } } + + pub fn mark_loaded_from_cache(&self, dep_node_index: DepNodeIndex, state: bool) { + debug!("mark_loaded_from_cache({:?}, {})", + self.data.as_ref().unwrap().current.borrow().data[dep_node_index].node, + state); + + self.data + .as_ref() + .unwrap() + .loaded_from_cache + .borrow_mut() + .insert(dep_node_index, state); + } + + pub fn was_loaded_from_cache(&self, dep_node: &DepNode) -> Option { + let data = self.data.as_ref().unwrap(); + let dep_node_index = data.current.borrow().node_to_node_index[dep_node]; + data.loaded_from_cache.borrow().get(&dep_node_index).cloned() + } } /// A "work product" is an intermediate result that we save into the @@ -920,27 +947,9 @@ struct DepNodeData { fingerprint: Fingerprint, } -/// `CurrentDepGraph` stores the dependency graph for the current session. -/// It will be populated as we run queries or tasks. -/// -/// The nodes in it are identified by an index (`DepNodeIndex`). -/// The data for each node is stored in its `DepNodeData`, found in the `data` field. -/// -/// We never remove nodes from the graph: they are only added. -/// -/// This struct uses two locks internally. The `data` and `node_to_node_index` fields are -/// locked separately. Operations that take a `DepNodeIndex` typically just access -/// the data field. -/// -/// The only operation that must manipulate both locks is adding new nodes, in which case -/// we first acquire the `node_to_node_index` lock and then, once a new node is to be inserted, -/// acquire the lock on `data.` pub(super) struct CurrentDepGraph { - data: Lock>, - node_to_node_index: Sharded>, - - /// Used to trap when a specific edge is added to the graph. - /// This is used for debug purposes and is only active with `debug_assertions`. + data: IndexVec, + node_to_node_index: FxHashMap, #[allow(dead_code)] forbidden_edge: Option, @@ -957,10 +966,8 @@ pub(super) struct CurrentDepGraph { /// the `DepGraph` is created. anon_id_seed: Fingerprint, - /// These are simple counters that are for profiling and - /// debugging and only active with `debug_assertions`. - total_read_count: AtomicU64, - total_duplicate_read_count: AtomicU64, + total_read_count: u64, + total_duplicate_read_count: u64, } impl CurrentDepGraph { @@ -994,20 +1001,20 @@ impl CurrentDepGraph { let new_node_count_estimate = (prev_graph_node_count * 102) / 100 + 200; CurrentDepGraph { - data: Lock::new(IndexVec::with_capacity(new_node_count_estimate)), - node_to_node_index: Sharded::new(|| FxHashMap::with_capacity_and_hasher( - new_node_count_estimate / sharded::SHARDS, + data: IndexVec::with_capacity(new_node_count_estimate), + node_to_node_index: FxHashMap::with_capacity_and_hasher( + new_node_count_estimate, Default::default(), - )), + ), anon_id_seed: stable_hasher.finish(), forbidden_edge, - total_read_count: AtomicU64::new(0), - total_duplicate_read_count: AtomicU64::new(0), + total_read_count: 0, + total_duplicate_read_count: 0, } } fn complete_task( - &self, + &mut self, node: DepNode, task_deps: TaskDeps, fingerprint: Fingerprint @@ -1015,7 +1022,7 @@ impl CurrentDepGraph { self.alloc_node(node, task_deps.reads, fingerprint) } - fn complete_anon_task(&self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex { + fn complete_anon_task(&mut self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex { debug_assert!(!kind.is_eval_always()); let mut hasher = StableHasher::new(); @@ -1040,30 +1047,28 @@ impl CurrentDepGraph { } fn alloc_node( - &self, + &mut self, dep_node: DepNode, edges: SmallVec<[DepNodeIndex; 8]>, fingerprint: Fingerprint ) -> DepNodeIndex { - debug_assert!(!self.node_to_node_index - .get_shard_by_value(&dep_node) - .lock() - .contains_key(&dep_node)); + debug_assert!(!self.node_to_node_index.contains_key(&dep_node)); self.intern_node(dep_node, edges, fingerprint) } fn intern_node( - &self, + &mut self, dep_node: DepNode, edges: SmallVec<[DepNodeIndex; 8]>, fingerprint: Fingerprint ) -> DepNodeIndex { - match self.node_to_node_index.get_shard_by_value(&dep_node).lock().entry(dep_node) { + debug_assert_eq!(self.node_to_node_index.len(), self.data.len()); + + match self.node_to_node_index.entry(dep_node) { Entry::Occupied(entry) => *entry.get(), Entry::Vacant(entry) => { - let mut data = self.data.lock(); - let dep_node_index = DepNodeIndex::new(data.len()); - data.push(DepNodeData { + let dep_node_index = DepNodeIndex::new(self.data.len()); + self.data.push(DepNodeData { node: dep_node, edges, fingerprint @@ -1082,7 +1087,7 @@ impl DepGraphData { if let Some(task_deps) = icx.task_deps { let mut task_deps = task_deps.lock(); if cfg!(debug_assertions) { - self.current.total_read_count.fetch_add(1, SeqCst); + self.current.lock().total_read_count += 1; } if task_deps.read_set.insert(source) { task_deps.reads.push(source); @@ -1090,9 +1095,9 @@ impl DepGraphData { #[cfg(debug_assertions)] { if let Some(target) = task_deps.node { - let data = self.current.data.lock(); - if let Some(ref forbidden_edge) = self.current.forbidden_edge { - let source = data[source].node; + let graph = self.current.lock(); + if let Some(ref forbidden_edge) = graph.forbidden_edge { + let source = graph.data[source].node; if forbidden_edge.test(&source, &target) { bug!("forbidden edge {:?} -> {:?} created", source, @@ -1102,7 +1107,7 @@ impl DepGraphData { } } } else if cfg!(debug_assertions) { - self.current.total_duplicate_read_count.fetch_add(1, SeqCst); + self.current.lock().total_duplicate_read_count += 1; } } }) diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc/dep_graph/serialized.rs index 4302195755ea5..b64f71ed908d8 100644 --- a/src/librustc/dep_graph/serialized.rs +++ b/src/librustc/dep_graph/serialized.rs @@ -2,9 +2,9 @@ use crate::dep_graph::DepNode; use crate::ich::Fingerprint; -use rustc_index::vec::{IndexVec, Idx}; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; -rustc_index::newtype_index! { +newtype_index! { pub struct SerializedDepNodeIndex { .. } } diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index cf268078a2c5d..968b0b9f2f2b7 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -259,8 +259,8 @@ trait Foo { This is similar to the second sub-error, but subtler. It happens in situations like the following: -```compile_fail,E0038 -trait Super {} +```compile_fail +trait Super {} trait Trait: Super { } @@ -270,21 +270,17 @@ struct Foo; impl Super for Foo{} impl Trait for Foo {} - -fn main() { - let x: Box; -} ``` Here, the supertrait might have methods as follows: ``` -trait Super { - fn get_a(&self) -> &A; // note that this is object safe! +trait Super { + fn get_a(&self) -> A; // note that this is object safe! } ``` -If the trait `Trait` was deriving from something like `Super` or +If the trait `Foo` was deriving from something like `Super` or `Super` (where `Foo` itself is `Foo`), this is okay, because given a type `get_a()` will definitely return an object of that type. @@ -470,6 +466,67 @@ fn main() { ``` "##, +// This shouldn't really ever trigger since the repeated value error comes first +E0136: r##" +A binary can only have one entry point, and by default that entry point is the +function `main()`. If there are multiple such functions, please rename one. +"##, + +E0137: r##" +More than one function was declared with the `#[main]` attribute. + +Erroneous code example: + +```compile_fail,E0137 +#![feature(main)] + +#[main] +fn foo() {} + +#[main] +fn f() {} // error: multiple functions with a `#[main]` attribute +``` + +This error indicates that the compiler found multiple functions with the +`#[main]` attribute. This is an error because there must be a unique entry +point into a Rust program. Example: + +``` +#![feature(main)] + +#[main] +fn f() {} // ok! +``` +"##, + +E0138: r##" +More than one function was declared with the `#[start]` attribute. + +Erroneous code example: + +```compile_fail,E0138 +#![feature(start)] + +#[start] +fn foo(argc: isize, argv: *const *const u8) -> isize {} + +#[start] +fn f(argc: isize, argv: *const *const u8) -> isize {} +// error: multiple 'start' functions +``` + +This error indicates that the compiler found multiple functions with the +`#[start]` attribute. This is an error because there must be a unique entry +point into a Rust program. Example: + +``` +#![feature(start)] + +#[start] +fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok! +``` +"##, + E0139: r##" #### Note: this error code is no longer emitted by the compiler. @@ -1523,51 +1580,8 @@ where ``` "##, -E0495: r##" -A lifetime cannot be determined in the given situation. - -Erroneous code example: - -```compile_fail,E0495 -fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { - match (&t,) { // error! - ((u,),) => u, - } -} - -let y = Box::new((42,)); -let x = transmute_lifetime(&y); -``` - -In this code, you have two ways to solve this issue: - 1. Enforce that `'a` lives at least as long as `'b`. - 2. Use the same lifetime requirement for both input and output values. - -So for the first solution, you can do it by replacing `'a` with `'a: 'b`: - -``` -fn transmute_lifetime<'a: 'b, 'b, T>(t: &'a (T,)) -> &'b T { - match (&t,) { // ok! - ((u,),) => u, - } -} -``` - -In the second you can do it by simply removing `'b` so they both use `'a`: - -``` -fn transmute_lifetime<'a, T>(t: &'a (T,)) -> &'a T { - match (&t,) { // ok! - ((u,),) => u, - } -} -``` -"##, - E0496: r##" -A lifetime name is shadowing another lifetime name. - -Erroneous code example: +A lifetime name is shadowing another lifetime name. Erroneous code example: ```compile_fail,E0496 struct Foo<'a> { @@ -1599,11 +1613,8 @@ fn main() { "##, E0497: r##" -#### Note: this error code is no longer emitted by the compiler. - -A stability attribute was used outside of the standard library. - -Erroneous code example: +A stability attribute was used outside of the standard library. Erroneous code +example: ```compile_fail #[stable] // error: stability attributes may not be used outside of the @@ -1615,6 +1626,33 @@ It is not possible to use stability attributes outside of the standard library. Also, for now, it is not possible to write deprecation messages either. "##, +E0512: r##" +Transmute with two differently sized types was attempted. Erroneous code +example: + +```compile_fail,E0512 +fn takes_u8(_: u8) {} + +fn main() { + unsafe { takes_u8(::std::mem::transmute(0u16)); } + // error: cannot transmute between types of different sizes, + // or dependently-sized types +} +``` + +Please use types with same size or use the expected type directly. Example: + +``` +fn takes_u8(_: u8) {} + +fn main() { + unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok! + // or: + unsafe { takes_u8(0u8); } // ok! +} +``` +"##, + E0517: r##" This error indicates that a `#[repr(..)]` attribute was placed on an unsupported item. @@ -1749,27 +1787,6 @@ To understand better how closures work in Rust, read: https://doc.rust-lang.org/book/ch13-01-closures.html "##, -E0566: r##" -Conflicting representation hints have been used on a same item. - -Erroneous code example: - -``` -#[repr(u32, u64)] // warning! -enum Repr { A } -``` - -In most cases (if not all), using just one representation hint is more than -enough. If you want to have a representation hint depending on the current -architecture, use `cfg_attr`. Example: - -``` -#[cfg_attr(linux, repr(u32))] -#[cfg_attr(not(linux), repr(u64))] -enum Repr { A } -``` -"##, - E0580: r##" The `main` function was incorrectly declared. @@ -1830,6 +1847,84 @@ See [RFC 1522] for more details. [RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md "##, +E0591: r##" +Per [RFC 401][rfc401], if you have a function declaration `foo`: + +``` +// For the purposes of this explanation, all of these +// different kinds of `fn` declarations are equivalent: +struct S; +fn foo(x: S) { /* ... */ } +# #[cfg(for_demonstration_only)] +extern "C" { fn foo(x: S); } +# #[cfg(for_demonstration_only)] +impl S { fn foo(self) { /* ... */ } } +``` + +the type of `foo` is **not** `fn(S)`, as one might expect. +Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`. +However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`, +so you rarely notice this: + +``` +# struct S; +# fn foo(_: S) {} +let x: fn(S) = foo; // OK, coerces +``` + +The reason that this matter is that the type `fn(S)` is not specific to +any particular function: it's a function _pointer_. So calling `x()` results +in a virtual call, whereas `foo()` is statically dispatched, because the type +of `foo` tells us precisely what function is being called. + +As noted above, coercions mean that most code doesn't have to be +concerned with this distinction. However, you can tell the difference +when using **transmute** to convert a fn item into a fn pointer. + +This is sometimes done as part of an FFI: + +```compile_fail,E0591 +extern "C" fn foo(userdata: Box) { + /* ... */ +} + +# fn callback(_: extern "C" fn(*mut i32)) {} +# use std::mem::transmute; +# unsafe { +let f: extern "C" fn(*mut i32) = transmute(foo); +callback(f); +# } +``` + +Here, transmute is being used to convert the types of the fn arguments. +This pattern is incorrect because, because the type of `foo` is a function +**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`) +is a function pointer, which is not zero-sized. +This pattern should be rewritten. There are a few possible ways to do this: + +- change the original fn declaration to match the expected signature, + and do the cast in the fn body (the preferred option) +- cast the fn item fo a fn pointer before calling transmute, as shown here: + + ``` + # extern "C" fn foo(_: Box) {} + # use std::mem::transmute; + # unsafe { + let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); + let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too + # } + ``` + +The same applies to transmutes to `*mut fn()`, which were observed in practice. +Note though that use of this type is generally incorrect. +The intention is typically to describe a function pointer, but just `fn()` +alone suffices for that. `*mut fn()` is a pointer to a fn pointer. +(Since these values are typically just passed to C code, however, this rarely +makes a difference in practice.) + +[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md +"##, + E0593: r##" You tried to supply an `Fn`-based type with an incorrect number of arguments than what was expected. @@ -1846,6 +1941,21 @@ fn main() { ``` "##, +E0601: r##" +No `main` function was found in a binary crate. To fix this error, add a +`main` function. For example: + +``` +fn main() { + // Your program will start here. + println!("Hello world!"); +} +``` + +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/ +"##, + E0602: r##" An unknown lint was used on the command line. @@ -2005,24 +2115,6 @@ a (non-transparent) struct containing a single float, while `Grams` is a transparent wrapper around a float. This can make a difference for the ABI. "##, -E0697: r##" -A closure has been used as `static`. - -Erroneous code example: - -```compile_fail,E0697 -fn main() { - static || {}; // used as `static` -} -``` - -Closures cannot be used as `static`. They "save" the environment, -and as such a static closure would save only a static environment -which would consist only of variables with a static lifetime. Given -this it would be better to use a proper function. The easiest fix -is to remove the `static` keyword. -"##, - E0698: r##" When using generators (or async) all type variables must be bound so a generator can be constructed. @@ -2045,8 +2137,8 @@ so that a generator can then be constructed: async fn bar() -> () {} async fn foo() { - bar::().await; - // ^^^^^^^^ specify type explicitly + bar::().await; + // ^^^^^^^^ specify type explicitly } ``` "##, @@ -2105,6 +2197,8 @@ on something other than a struct or enum. Examples of erroneous code: ```compile_fail,E0701 +# #![feature(non_exhaustive)] + #[non_exhaustive] trait Foo { } ``` @@ -2124,84 +2218,6 @@ static X: u32 = 42; ``` "##, -E0728: r##" -[`await`] has been used outside [`async`] function or block. - -Erroneous code examples: - -```edition2018,compile_fail,E0728 -# use std::pin::Pin; -# use std::future::Future; -# use std::task::{Context, Poll}; -# -# struct WakeOnceThenComplete(bool); -# -# fn wake_and_yield_once() -> WakeOnceThenComplete { -# WakeOnceThenComplete(false) -# } -# -# impl Future for WakeOnceThenComplete { -# type Output = (); -# fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { -# if self.0 { -# Poll::Ready(()) -# } else { -# cx.waker().wake_by_ref(); -# self.0 = true; -# Poll::Pending -# } -# } -# } -# -fn foo() { - wake_and_yield_once().await // `await` is used outside `async` context -} -``` - -[`await`] is used to suspend the current computation until the given -future is ready to produce a value. So it is legal only within -an [`async`] context, like an `async fn` or an `async` block. - -```edition2018 -# use std::pin::Pin; -# use std::future::Future; -# use std::task::{Context, Poll}; -# -# struct WakeOnceThenComplete(bool); -# -# fn wake_and_yield_once() -> WakeOnceThenComplete { -# WakeOnceThenComplete(false) -# } -# -# impl Future for WakeOnceThenComplete { -# type Output = (); -# fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { -# if self.0 { -# Poll::Ready(()) -# } else { -# cx.waker().wake_by_ref(); -# self.0 = true; -# Poll::Pending -# } -# } -# } -# -async fn foo() { - wake_and_yield_once().await // `await` is used within `async` function -} - -fn bar(x: u8) -> impl Future { - async move { - wake_and_yield_once().await; // `await` is used within `async` block - x - } -} -``` - -[`async`]: https://doc.rust-lang.org/std/keyword.async.html -[`await`]: https://doc.rust-lang.org/std/keyword.await.html -"##, - E0734: r##" A stability attribute has been used outside of the standard library. @@ -2218,25 +2234,6 @@ These attributes are meant to only be used by the standard library and are rejected in your own crates. "##, -E0736: r##" -#[track_caller] and #[naked] cannot be applied to the same function. - -Erroneous code example: - -```compile_fail,E0736 -#![feature(track_caller)] - -#[naked] -#[track_caller] -fn foo() {} -``` - -This is primarily due to ABI incompatibilities between the two attributes. -See [RFC 2091] for details on this and other limitations. - -[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md -"##, - ; // E0006, // merged with E0005 // E0101, // replaced with E0282 @@ -2246,7 +2243,7 @@ See [RFC 2091] for details on this and other limitations. // E0272, // on_unimplemented #0 // E0273, // on_unimplemented #1 // E0274, // on_unimplemented #2 -// E0278, // requirement is not satisfied + E0278, // requirement is not satisfied E0279, // requirement is not satisfied E0280, // requirement is not satisfied // E0285, // overflow evaluation builtin bounds @@ -2278,6 +2275,9 @@ See [RFC 2091] for details on this and other limitations. 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 + E0566, // conflicting representation hints E0623, // lifetime mismatch where both parameters are anonymous regions E0628, // generators cannot have explicit parameters E0631, // type mismatch in closure arguments @@ -2285,14 +2285,15 @@ See [RFC 2091] for details on this and other limitations. E0657, // `impl Trait` can only capture lifetimes bound at the fn level E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders -// E0707, // multiple elided lifetimes used in arguments of `async fn` + E0697, // closures cannot be static + E0707, // multiple elided lifetimes used in arguments of `async fn` E0708, // `async` non-`move` closures with parameters are not currently // supported -// E0709, // multiple different lifetimes used in arguments of `async fn` + 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 // E0702, // replaced with a generic attribute input check E0726, // non-explicit (not `'_`) elided lifetime in unsupported position E0727, // `async` generators are not yet supported - E0739, // invalid track_caller application/syntax + E0728, // `await` must be in an `async` function or block } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index c37fec982b116..d5e956555bdfb 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -11,7 +11,7 @@ use crate::ty::TyCtxt; use crate::ty::query::Providers; use std::fmt::{self, Display}; -use syntax::{attr, symbol::sym}; +use syntax::symbol::sym; use syntax_pos::Span; #[derive(Copy, Clone, PartialEq)] @@ -103,8 +103,6 @@ impl CheckAttrVisitor<'tcx> { self.check_marker(attr, item, target) } else if attr.check_name(sym::target_feature) { self.check_target_feature(attr, item, target) - } else if attr.check_name(sym::track_caller) { - self.check_track_caller(attr, &item, target) } else { true }; @@ -137,32 +135,6 @@ impl CheckAttrVisitor<'tcx> { } } - /// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid. - fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) -> bool { - if target != Target::Fn { - struct_span_err!( - self.tcx.sess, - attr.span, - E0739, - "attribute should be applied to function" - ) - .span_label(item.span, "not a function") - .emit(); - false - } else if attr::contains_name(&item.attrs, sym::naked) { - struct_span_err!( - self.tcx.sess, - attr.span, - E0736, - "cannot use `#[track_caller]` with `#[naked]`", - ) - .emit(); - false - } else { - true - } - } - /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid. fn check_non_exhaustive( &self, diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index a071a539e01df..f7d31ca06ee56 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -6,7 +6,7 @@ use crate::ty; use crate::util::nodemap::DefIdMap; use syntax::ast; -use syntax_expand::base::MacroKind; +use syntax::ext::base::MacroKind; use syntax::ast::NodeId; use syntax_pos::Span; use rustc_macros::HashStable; diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 13200b38f2cda..d0bdc14913183 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -1,9 +1,9 @@ use crate::ty::{self, TyCtxt}; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use std::fmt; use std::u32; -rustc_index::newtype_index! { +newtype_index! { pub struct CrateId { ENCODABLE = custom } @@ -87,7 +87,7 @@ impl fmt::Display for CrateNum { impl rustc_serialize::UseSpecializedEncodable for CrateNum {} impl rustc_serialize::UseSpecializedDecodable for CrateNum {} -rustc_index::newtype_index! { +newtype_index! { /// A DefIndex is an index into the hir-map for a crate, identifying a /// particular definition. It should really be considered an interned /// shorthand for a particular DefPath. diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 05bdd0887f0f6..d1ebdd2f086ab 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -633,6 +633,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { TyKind::Typeof(ref expression) => { visitor.visit_anon_const(expression) } + TyKind::CVarArgs(ref lt) => { + visitor.visit_lifetime(lt) + } TyKind::Infer | TyKind::Err => {} } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 002e6874466bb..d0a9d967a649d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -52,7 +52,7 @@ use crate::util::common::FN_OUTPUT_NAME; use crate::util::nodemap::{DefIdMap, NodeMap}; use errors::Applicability; use rustc_data_structures::fx::FxHashSet; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::sync::Lrc; @@ -64,15 +64,14 @@ use syntax::ast; use syntax::ptr::P as AstP; use syntax::ast::*; use syntax::errors; -use syntax_expand::base::SpecialDerives; +use syntax::ext::base::SpecialDerives; +use syntax::ext::hygiene::ExpnId; use syntax::print::pprust; -use syntax::parse::token::{self, Nonterminal, Token}; -use syntax::tokenstream::{TokenStream, TokenTree}; -use syntax::sess::ParseSess; 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::hygiene::ExpnId; use syntax_pos::Span; const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; @@ -83,12 +82,9 @@ pub struct LoweringContext<'a> { /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes. sess: &'a Session, - resolver: &'a mut dyn Resolver, + cstore: &'a dyn CrateStore, - /// HACK(Centril): there is a cyclic dependency between the parser and lowering - /// if we don't have this function pointer. To avoid that dependency so that - /// librustc is independent of the parser, we use dynamic dispatch here. - nt_to_tokenstream: NtToTokenstream, + resolver: &'a mut dyn Resolver, /// The items being lowered are collected here. items: BTreeMap, @@ -158,8 +154,6 @@ pub struct LoweringContext<'a> { } pub trait Resolver { - fn cstore(&self) -> &dyn CrateStore; - /// Obtains resolution for a `NodeId` with a single resolution. fn get_partial_res(&mut self, id: NodeId) -> Option; @@ -186,8 +180,6 @@ pub trait Resolver { fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool; } -type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream; - /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, /// and if so, what meaning it has. #[derive(Debug)] @@ -240,23 +232,21 @@ impl<'a> ImplTraitContext<'a> { pub fn lower_crate( sess: &Session, + cstore: &dyn CrateStore, dep_graph: &DepGraph, krate: &Crate, resolver: &mut dyn Resolver, - nt_to_tokenstream: NtToTokenstream, ) -> hir::Crate { // We're constructing the HIR here; we don't care what we will // read, since we haven't even constructed the *input* to // incr. comp. yet. dep_graph.assert_ignored(); - let _prof_timer = sess.prof.generic_activity("hir_lowering"); - LoweringContext { crate_root: sess.parse_sess.injected_crate_name.try_get().copied(), sess, + cstore, resolver, - nt_to_tokenstream, items: BTreeMap::new(), trait_items: BTreeMap::new(), impl_items: BTreeMap::new(), @@ -790,15 +780,15 @@ impl<'a> LoweringContext<'a> { // really show up for end-user. let (str_name, kind) = match hir_name { ParamName::Plain(ident) => ( - ident.name, + ident.as_interned_str(), hir::LifetimeParamKind::InBand, ), ParamName::Fresh(_) => ( - kw::UnderscoreLifetime, + kw::UnderscoreLifetime.as_interned_str(), hir::LifetimeParamKind::Elided, ), ParamName::Error => ( - kw::UnderscoreLifetime, + kw::UnderscoreLifetime.as_interned_str(), hir::LifetimeParamKind::Error, ), }; @@ -854,7 +844,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() + self.in_scope_lifetimes.len(); + let index = self.lifetimes_to_define.len(); let hir_name = ParamName::Fresh(index); self.lifetimes_to_define.push((span, hir_name)); hir_name @@ -978,7 +968,7 @@ impl<'a> LoweringContext<'a> { if id.is_local() { self.resolver.definitions().def_key(id.index) } else { - self.resolver.cstore().def_key(id) + self.cstore.def_key(id) } } @@ -998,12 +988,10 @@ impl<'a> LoweringContext<'a> { // lower attributes (we use the AST version) there is nowhere to keep // the `HirId`s. We don't actually need HIR version of attributes anyway. Attribute { - item: AttrItem { - path: attr.path.clone(), - tokens: self.lower_token_stream(attr.tokens.clone()), - }, id: attr.id, style: attr.style, + path: attr.path.clone(), + tokens: self.lower_token_stream(attr.tokens.clone()), is_sugared_doc: attr.is_sugared_doc, span: attr.span, } @@ -1030,7 +1018,7 @@ impl<'a> LoweringContext<'a> { fn lower_token(&mut self, token: Token) -> TokenStream { match token.kind { token::Interpolated(nt) => { - let tts = (self.nt_to_tokenstream)(&nt, &self.sess.parse_sess, token.span); + let tts = nt.to_tokenstream(&self.sess.parse_sess, token.span); self.lower_token_stream(tts) } _ => TokenTree::Token(token).into(), @@ -1347,8 +1335,13 @@ impl<'a> LoweringContext<'a> { } } } - TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"), - TyKind::CVarArgs => bug!("`TyKind::CVarArgs` should have been handled elsewhere"), + 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()); + let lt = self.new_implicit_lifetime(span); + hir::TyKind::CVarArgs(lt) + }, }; hir::Ty { @@ -1588,7 +1581,7 @@ impl<'a> LoweringContext<'a> { self.context.resolver.definitions().create_def_with_parent( self.parent, def_node_id, - DefPathData::LifetimeNs(name.ident().name), + DefPathData::LifetimeNs(name.ident().as_interned_str()), ExpnId::root(), lifetime.span); @@ -1725,8 +1718,8 @@ impl<'a> LoweringContext<'a> { return n; } assert!(!def_id.is_local()); - let item_generics = self.resolver.cstore() - .item_generics_cloned_untracked(def_id, self.sess); + let item_generics = + self.cstore.item_generics_cloned_untracked(def_id, self.sess); let n = item_generics.own_counts().lifetimes; self.type_def_lifetime_params.insert(def_id, n); n @@ -2100,14 +2093,7 @@ impl<'a> LoweringContext<'a> { } fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> hir::HirVec { - // Skip the `...` (`CVarArgs`) trailing arguments from the AST, - // as they are not explicit in HIR/Ty function signatures. - // (instead, the `c_variadic` flag is set to `true`) - let mut inputs = &decl.inputs[..]; - if decl.c_variadic() { - inputs = &inputs[..inputs.len() - 1]; - } - inputs + decl.inputs .iter() .map(|param| match param.pat.kind { PatKind::Ident(_, ident, _) => ident, @@ -2144,19 +2130,10 @@ impl<'a> LoweringContext<'a> { self.anonymous_lifetime_mode }; - let c_variadic = decl.c_variadic(); - // Remember how many lifetimes were already around so that we can // only look at the lifetime parameters introduced by the arguments. let inputs = self.with_anonymous_lifetime_mode(lt_mode, |this| { - // Skip the `...` (`CVarArgs`) trailing arguments from the AST, - // as they are not explicit in HIR/Ty function signatures. - // (instead, the `c_variadic` flag is set to `true`) - let mut inputs = &decl.inputs[..]; - if c_variadic { - inputs = &inputs[..inputs.len() - 1]; - } - inputs + decl.inputs .iter() .map(|param| { if let Some((_, ibty)) = &mut in_band_ty_params { @@ -2191,7 +2168,7 @@ impl<'a> LoweringContext<'a> { P(hir::FnDecl { inputs, output, - c_variadic, + c_variadic: decl.c_variadic, implicit_self: decl.inputs.get(0).map_or( hir::ImplicitSelfKind::None, |arg| { @@ -3289,14 +3266,10 @@ impl<'a> LoweringContext<'a> { let id = self.sess.next_node_id(); self.new_named_lifetime(id, span, hir::LifetimeName::Error) } - // `PassThrough` is the normal case. - // `new_error_lifetime`, which would usually be used in the case of `ReportError`, - // is unsuitable here, as these can occur from missing lifetime parameters in a - // `PathSegment`, for which there is no associated `'_` or `&T` with no explicit - // lifetime. Instead, we simply create an implicit lifetime, which will be checked - // later, at which point a suitable error will be emitted. - | AnonymousLifetimeMode::PassThrough - | AnonymousLifetimeMode::ReportError => self.new_implicit_lifetime(span), + // This is the normal case. + AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span), + + AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span), } } diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index d5fcc0ef6ede8..50fceacaa4486 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -89,14 +89,9 @@ impl LoweringContext<'_> { hir::MatchSource::Normal, ), ExprKind::Async(capture_clause, closure_node_id, ref block) => { - self.make_async_expr( - capture_clause, - closure_node_id, - None, - block.span, - hir::AsyncGeneratorKind::Block, - |this| this.with_new_scopes(|this| this.lower_block_expr(block)), - ) + self.make_async_expr(capture_clause, closure_node_id, None, block.span, |this| { + this.with_new_scopes(|this| this.lower_block_expr(block)) + }) } ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr), ExprKind::Closure( @@ -397,35 +392,19 @@ impl LoweringContext<'_> { ) } - /// Desugar `try { ; }` into `{ ; ::std::ops::Try::from_ok() }`, - /// `try { ; }` into `{ ; ::std::ops::Try::from_ok(()) }` - /// and save the block id to use it as a break target for desugaring of the `?` operator. fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind { self.with_catch_scope(body.id, |this| { - let mut block = this.lower_block(body, true).into_inner(); - - let try_span = this.mark_span_with_reason( + let unstable_span = this.mark_span_with_reason( DesugaringKind::TryBlock, body.span, this.allow_try_trait.clone(), ); - - // Final expression of the block (if present) or `()` with span at the end of block - let tail_expr = block.expr.take().map_or_else( - || this.expr_unit(this.sess.source_map().end_point(try_span)), + let mut block = this.lower_block(body, true).into_inner(); + let tail = block.expr.take().map_or_else( + || this.expr_unit(this.sess.source_map().end_point(unstable_span)), |x: P| x.into_inner(), ); - - let ok_wrapped_span = this.mark_span_with_reason( - DesugaringKind::TryBlock, - tail_expr.span, - None - ); - - // `::std::ops::Try::from_ok($tail_expr)` - block.expr = Some(this.wrap_in_try_constructor( - sym::from_ok, try_span, tail_expr, ok_wrapped_span)); - + block.expr = Some(this.wrap_in_try_constructor(sym::from_ok, tail, unstable_span)); hir::ExprKind::Block(P(block), None) }) } @@ -433,13 +412,12 @@ impl LoweringContext<'_> { fn wrap_in_try_constructor( &mut self, method: Symbol, - method_span: Span, - expr: hir::Expr, - overall_span: Span, + e: hir::Expr, + unstable_span: Span, ) -> P { let path = &[sym::ops, sym::Try, method]; - let constructor = P(self.expr_std_path(method_span, path, None, ThinVec::new())); - P(self.expr_call(overall_span, constructor, hir_vec![expr])) + let from_err = P(self.expr_std_path(unstable_span, path, None, ThinVec::new())); + P(self.expr_call(e.span, from_err, hir_vec![e])) } fn lower_arm(&mut self, arm: &Arm) -> hir::Arm { @@ -462,7 +440,6 @@ impl LoweringContext<'_> { closure_node_id: NodeId, ret_ty: Option>, span: Span, - async_gen_kind: hir::AsyncGeneratorKind, body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr, ) -> hir::ExprKind { let capture_clause = self.lower_capture_clause(capture_clause); @@ -473,10 +450,11 @@ impl LoweringContext<'_> { let ast_decl = FnDecl { inputs: vec![], output, + c_variadic: false }; let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None); let body_id = self.lower_fn_body(&ast_decl, |this| { - this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind)); + this.generator_kind = Some(hir::GeneratorKind::Async); body(this) }); @@ -528,7 +506,7 @@ impl LoweringContext<'_> { /// ``` fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind { match self.generator_kind { - Some(hir::GeneratorKind::Async(_)) => {}, + Some(hir::GeneratorKind::Async) => {}, Some(hir::GeneratorKind::Gen) | None => { let mut err = struct_span_err!( @@ -733,7 +711,7 @@ impl LoweringContext<'_> { Movability::Static => hir::GeneratorMovability::Static, }) }, - Some(hir::GeneratorKind::Async(_)) => { + Some(hir::GeneratorKind::Async) => { bug!("non-`async` closure body turned `async` during lowering"); }, None => { @@ -761,6 +739,7 @@ impl LoweringContext<'_> { let outer_decl = FnDecl { inputs: decl.inputs.clone(), output: FunctionRetTy::Default(fn_decl_span), + c_variadic: false, }; // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the @@ -792,12 +771,10 @@ impl LoweringContext<'_> { None }; let async_body = this.make_async_expr( - capture_clause, - closure_id, - async_ret_ty, - body.span, - hir::AsyncGeneratorKind::Closure, - |this| this.with_new_scopes(|this| this.lower_expr(body)), + capture_clause, closure_id, async_ret_ty, body.span, + |this| { + this.with_new_scopes(|this| this.lower_expr(body)) + } ); this.expr(fn_decl_span, async_body, ThinVec::new()) }); @@ -1013,7 +990,7 @@ impl LoweringContext<'_> { fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind { match self.generator_kind { Some(hir::GeneratorKind::Gen) => {}, - Some(hir::GeneratorKind::Async(_)) => { + Some(hir::GeneratorKind::Async) => { span_err!( self.sess, span, @@ -1062,9 +1039,10 @@ impl LoweringContext<'_> { ) -> hir::Expr { // expand let mut head = self.lower_expr(head); + let head_sp = head.span; let desugared_span = self.mark_span_with_reason( DesugaringKind::ForLoop, - head.span, + head_sp, None, ); head.span = desugared_span; @@ -1110,21 +1088,21 @@ impl LoweringContext<'_> { // `match ::std::iter::Iterator::next(&mut iter) { ... }` let match_expr = { - let iter = P(self.expr_ident(desugared_span, iter, iter_pat_nid)); - let ref_mut_iter = self.expr_mut_addr_of(desugared_span, iter); + let iter = P(self.expr_ident(head_sp, iter, iter_pat_nid)); + let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter); let next_path = &[sym::iter, sym::Iterator, sym::next]; let next_expr = P(self.expr_call_std_path( - desugared_span, + head_sp, next_path, hir_vec![ref_mut_iter], )); let arms = hir_vec![pat_arm, break_arm]; - self.expr_match(desugared_span, next_expr, arms, hir::MatchSource::ForLoopDesugar) + self.expr_match(head_sp, next_expr, arms, hir::MatchSource::ForLoopDesugar) }; - let match_stmt = self.stmt_expr(desugared_span, match_expr); + let match_stmt = self.stmt_expr(head_sp, match_expr); - let next_expr = P(self.expr_ident(desugared_span, next_ident, next_pat_hid)); + let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_hid)); // `let mut __next` let next_let = self.stmt_let_pat( @@ -1139,7 +1117,7 @@ impl LoweringContext<'_> { let pat = self.lower_pat(pat); let pat_let = self.stmt_let_pat( ThinVec::new(), - desugared_span, + head_sp, Some(next_expr), pat, hir::LocalSource::ForLoopDesugar, @@ -1176,14 +1154,14 @@ impl LoweringContext<'_> { let into_iter_path = &[sym::iter, sym::IntoIterator, sym::into_iter]; P(self.expr_call_std_path( - desugared_span, + head_sp, into_iter_path, hir_vec![head], )) }; let match_expr = P(self.expr_match( - desugared_span, + head_sp, into_iter_expr, hir_vec![iter_arm], hir::MatchSource::ForLoopDesugar, @@ -1195,7 +1173,7 @@ impl LoweringContext<'_> { // surrounding scope of the `match` since the `match` is not a terminating scope. // // Also, add the attributes to the outer returned expr node. - self.expr_drop_temps(desugared_span, match_expr, e.attrs.clone()) + self.expr_drop_temps(head_sp, match_expr, e.attrs.clone()) } /// Desugar `ExprKind::Try` from: `?` into: @@ -1269,7 +1247,7 @@ impl LoweringContext<'_> { self.expr_call_std_path(try_span, from_path, hir_vec![err_expr]) }; let from_err_expr = - self.wrap_in_try_constructor(sym::from_error, unstable_span, from_expr, try_span); + self.wrap_in_try_constructor(sym::from_error, from_expr, unstable_span); let thin_attrs = ThinVec::from(attrs); let catch_scope = self.catch_scopes.last().map(|x| *x); let ret_expr = if let Some(catch_node) = catch_scope { diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 73d2ac5c134d3..7159db736a711 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -18,7 +18,7 @@ use smallvec::SmallVec; use syntax::attr; use syntax::ast::*; use syntax::visit::{self, Visitor}; -use syntax_expand::base::SpecialDerives; +use syntax::ext::base::SpecialDerives; use syntax::source_map::{respan, DesugaringKind, Spanned}; use syntax::symbol::{kw, sym}; use syntax_pos::Span; @@ -1222,11 +1222,7 @@ impl LoweringContext<'_> { } let async_expr = this.make_async_expr( - CaptureBy::Value, - closure_id, - None, - body.span, - hir::AsyncGeneratorKind::Fn, + CaptureBy::Value, closure_id, None, body.span, |this| { // Create a block from the user's function body: let user_body = this.lower_block_expr(body); diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 307dbe7dab080..c69d682b6f796 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -5,7 +5,7 @@ use crate::hir::map::HirEntryMap; use crate::hir::def_id::{LOCAL_CRATE, CrateNum}; use crate::hir::intravisit::{Visitor, NestedVisitorMap}; use rustc_data_structures::svh::Svh; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use crate::ich::Fingerprint; use crate::middle::cstore::CrateStore; use crate::session::CrateDisambiguator; @@ -17,7 +17,7 @@ use syntax_pos::Span; use std::iter::repeat; use crate::ich::StableHashingContext; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; /// A visitor that walks over the HIR and collects `Node`s into a HIR map. pub(super) struct NodeCollector<'a, 'hir> { @@ -186,13 +186,13 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { }); let mut upstream_crates: Vec<_> = cstore.crates_untracked().iter().map(|&cnum| { - let name = cstore.crate_name_untracked(cnum); + 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) }).collect(); - upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis)); + upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name, dis)); // We hash the final, remapped names of all local source files so we // don't have to include the path prefix remapping commandline args. @@ -602,7 +602,9 @@ impl<'hir, T> HashStable> for HirItemLike where T: HashStable>, { - fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'hir>, + hasher: &mut StableHasher) { hcx.while_hashing_hir_bodies(self.hash_bodies, |hcx| { self.item_like.hash_stable(hcx, hasher); }); diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 7c8fdcc8b12e9..1997e2aab35e8 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -2,7 +2,7 @@ use crate::hir::map::definitions::*; use crate::hir::def_id::DefIndex; use syntax::ast::*; -use syntax_expand::hygiene::ExpnId; +use syntax::ext::hygiene::ExpnId; use syntax::visit; use syntax::symbol::{kw, sym}; use syntax::parse::token::{self, Token}; @@ -57,7 +57,7 @@ impl<'a> DefCollector<'a> { // For async functions, we need to create their inner defs inside of a // closure to match their desugared representation. - let fn_def_data = DefPathData::ValueNs(name); + let fn_def_data = DefPathData::ValueNs(name.as_interned_str()); let fn_def = self.create_def(id, fn_def_data, span); return self.with_parent(fn_def, |this| { this.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); @@ -83,13 +83,14 @@ impl<'a> DefCollector<'a> { .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)); } } - fn visit_macro_invoc(&mut self, id: NodeId) { + pub fn visit_macro_invoc(&mut self, id: NodeId) { self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def); } } @@ -108,7 +109,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { ItemKind::Mod(..) | ItemKind::Trait(..) | ItemKind::TraitAlias(..) | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::OpaqueTy(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | - ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), + ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.as_interned_str()), ItemKind::Fn( ref decl, ref header, @@ -126,8 +127,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { ) } ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => - DefPathData::ValueNs(i.ident.name), - ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.name), + DefPathData::ValueNs(i.ident.as_interned_str()), + ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.as_interned_str()), ItemKind::Mac(..) => return self.visit_macro_invoc(i.id), ItemKind::GlobalAsm(..) => DefPathData::Misc, ItemKind::Use(..) => { @@ -161,7 +162,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } let def = self.create_def(foreign_item.id, - DefPathData::ValueNs(foreign_item.ident.name), + DefPathData::ValueNs(foreign_item.ident.as_interned_str()), foreign_item.span); self.with_parent(def, |this| { @@ -174,7 +175,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { return self.visit_macro_invoc(v.id); } let def = self.create_def(v.id, - DefPathData::TypeNs(v.ident.name), + DefPathData::TypeNs(v.ident.as_interned_str()), v.span); self.with_parent(def, |this| { if let Some(ctor_hir_id) = v.data.ctor_id() { @@ -201,7 +202,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { self.visit_macro_invoc(param.id); return; } - let name = param.ident.name; + let name = param.ident.as_interned_str(); let def_path_data = match param.kind { GenericParamKind::Lifetime { .. } => DefPathData::LifetimeNs(name), GenericParamKind::Type { .. } => DefPathData::TypeNs(name), @@ -215,9 +216,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_trait_item(&mut self, ti: &'a TraitItem) { let def_data = match ti.kind { TraitItemKind::Method(..) | TraitItemKind::Const(..) => - DefPathData::ValueNs(ti.ident.name), + DefPathData::ValueNs(ti.ident.as_interned_str()), TraitItemKind::Type(..) => { - DefPathData::TypeNs(ti.ident.name) + DefPathData::TypeNs(ti.ident.as_interned_str()) }, TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), }; @@ -242,10 +243,12 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { body, ) } - ImplItemKind::Method(..) | - ImplItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name), + ImplItemKind::Method(..) | ImplItemKind::Const(..) => + DefPathData::ValueNs(ii.ident.as_interned_str()), ImplItemKind::TyAlias(..) | - ImplItemKind::OpaqueTy(..) => DefPathData::TypeNs(ii.ident.name), + ImplItemKind::OpaqueTy(..) => { + DefPathData::TypeNs(ii.ident.as_interned_str()) + }, ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id), }; diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 5993a97c40d6a..187bc59332460 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -11,14 +11,14 @@ use crate::session::CrateDisambiguator; use crate::util::nodemap::NodeMap; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::{IndexVec}; +use rustc_data_structures::indexed_vec::{IndexVec}; use rustc_data_structures::stable_hasher::StableHasher; use std::borrow::Borrow; use std::fmt::Write; use std::hash::Hash; use syntax::ast; -use syntax_expand::hygiene::ExpnId; -use syntax::symbol::{Symbol, sym}; +use syntax::ext::hygiene::ExpnId; +use syntax::symbol::{Symbol, sym, InternedString}; use syntax_pos::{Span, DUMMY_SP}; /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa. @@ -111,7 +111,7 @@ pub struct Definitions { /// A unique identifier that we can use to lookup a definition /// precisely. It combines the index of the definition's parent (if /// any) with a `DisambiguatedDefPathData`. -#[derive(Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, PartialEq, Debug, Hash, RustcEncodable, RustcDecodable)] pub struct DefKey { /// The parent path. pub parent: Option, @@ -136,9 +136,7 @@ impl DefKey { ::std::mem::discriminant(data).hash(&mut hasher); if let Some(name) = data.get_opt_name() { - // Get a stable hash by considering the symbol chars rather than - // the symbol index. - name.as_str().hash(&mut hasher); + name.hash(&mut hasher); } disambiguator.hash(&mut hasher); @@ -164,13 +162,13 @@ impl DefKey { /// between them. This introduces some artificial ordering dependency /// 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, RustcEncodable, RustcDecodable)] +#[derive(Clone, PartialEq, Debug, Hash, RustcEncodable, RustcDecodable)] pub struct DisambiguatedDefPathData { pub data: DefPathData, pub disambiguator: u32 } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable)] pub struct DefPath { /// The path leading from the crate root to the item. pub data: Vec, @@ -220,7 +218,7 @@ impl DefPath { for component in &self.data { write!(s, "::{}[{}]", - component.data.as_symbol(), + component.data.as_interned_str(), component.disambiguator) .unwrap(); } @@ -240,11 +238,11 @@ impl DefPath { for component in &self.data { if component.disambiguator == 0 { - write!(s, "::{}", component.data.as_symbol()).unwrap(); + write!(s, "::{}", component.data.as_interned_str()).unwrap(); } else { write!(s, "{}[{}]", - component.data.as_symbol(), + component.data.as_interned_str(), component.disambiguator) .unwrap(); } @@ -264,11 +262,11 @@ impl DefPath { opt_delimiter.map(|d| s.push(d)); opt_delimiter = Some('-'); if component.disambiguator == 0 { - write!(s, "{}", component.data.as_symbol()).unwrap(); + write!(s, "{}", component.data.as_interned_str()).unwrap(); } else { write!(s, "{}[{}]", - component.data.as_symbol(), + component.data.as_interned_str(), component.disambiguator) .unwrap(); } @@ -292,13 +290,13 @@ pub enum DefPathData { /// An impl. Impl, /// Something in the type namespace. - TypeNs(Symbol), + TypeNs(InternedString), /// Something in the value namespace. - ValueNs(Symbol), + ValueNs(InternedString), /// Something in the macro namespace. - MacroNs(Symbol), + MacroNs(InternedString), /// Something in the lifetime namespace. - LifetimeNs(Symbol), + LifetimeNs(InternedString), /// A closure expression. ClosureExpr, @@ -313,7 +311,7 @@ pub enum DefPathData { /// Identifies a piece of crate metadata that is global to a whole crate /// (as opposed to just one item). `GlobalMetaData` components are only /// supposed to show up right below the crate root. - GlobalMetaData(Symbol), + GlobalMetaData(InternedString), } #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, @@ -547,7 +545,7 @@ impl Definitions { } impl DefPathData { - pub fn get_opt_name(&self) -> Option { + pub fn get_opt_name(&self) -> Option { use self::DefPathData::*; match *self { TypeNs(name) | @@ -566,15 +564,15 @@ impl DefPathData { } } - pub fn as_symbol(&self) -> Symbol { + pub fn as_interned_str(&self) -> InternedString { use self::DefPathData::*; - match *self { + let s = match *self { TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | GlobalMetaData(name) => { - name + return name } // Note that this does not show up in user print-outs. CrateRoot => sym::double_braced_crate, @@ -584,11 +582,13 @@ impl DefPathData { Ctor => sym::double_braced_constructor, AnonConst => sym::double_braced_constant, ImplTrait => sym::double_braced_opaque, - } + }; + + s.as_interned_str() } pub fn to_string(&self) -> String { - self.as_symbol().to_string() + self.as_interned_str().to_string() } } @@ -599,6 +599,7 @@ macro_rules! define_global_metadata_kind { (pub enum GlobalMetaDataKind { $($variant:ident),* }) => ( + #[derive(Clone, Copy, Debug, Hash, RustcEncodable, RustcDecodable)] pub enum GlobalMetaDataKind { $($variant),* } @@ -610,7 +611,7 @@ macro_rules! define_global_metadata_kind { definitions.create_def_with_parent( CRATE_DEF_INDEX, ast::DUMMY_NODE_ID, - DefPathData::GlobalMetaData(instance.name()), + DefPathData::GlobalMetaData(instance.name().as_interned_str()), ExpnId::root(), DUMMY_SP ); @@ -624,7 +625,7 @@ macro_rules! define_global_metadata_kind { let def_key = DefKey { parent: Some(CRATE_DEF_INDEX), disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::GlobalMetaData(self.name()), + data: DefPathData::GlobalMetaData(self.name().as_interned_str()), disambiguator: 0, } }; diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index f839087ec0271..42a4a9909f8a9 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -17,10 +17,10 @@ use crate::util::common::time; use rustc_target::spec::abi::Abi; use rustc_data_structures::svh::Svh; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use syntax::ast::{self, Name, NodeId}; use syntax::source_map::Spanned; -use syntax_expand::base::MacroKind; +use syntax::ext::base::MacroKind; use syntax_pos::{Span, DUMMY_SP}; pub mod blocks; @@ -818,32 +818,6 @@ impl<'hir> Map<'hir> { CRATE_HIR_ID } - /// When on a match arm tail expression or on a match arm, give back the enclosing `match` - /// expression. - /// - /// Used by error reporting when there's a type error in a match arm caused by the `match` - /// expression needing to be unit. - pub fn get_match_if_cause(&self, hir_id: HirId) -> Option<&Expr> { - for (_, node) in ParentHirIterator::new(hir_id, &self) { - match node { - Node::Item(_) | - Node::ForeignItem(_) | - Node::TraitItem(_) | - Node::ImplItem(_) => break, - Node::Expr(expr) => match expr.kind { - ExprKind::Match(_, _, _) => return Some(expr), - _ => {} - }, - Node::Stmt(stmt) => match stmt.kind { - StmtKind::Local(_) => break, - _ => {} - } - _ => {} - } - } - None - } - /// Returns the nearest enclosing scope. A scope is roughly an item or block. pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option { for (hir_id, node) in ParentHirIterator::new(hir_id, &self) { @@ -1222,8 +1196,6 @@ pub fn map_crate<'hir>(sess: &crate::session::Session, forest: &'hir Forest, definitions: &'hir Definitions) -> Map<'hir> { - let _prof_timer = sess.prof.generic_activity("build_hir_map"); - // Build the reverse mapping of `node_to_hir_id`. let hir_to_node_id = definitions.node_to_hir_id.iter_enumerated() .map(|(node_id, &hir_id)| (hir_id, node_id)).collect(); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 38c84ad33478b..6a88ae077c8da 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -19,7 +19,7 @@ use crate::ty::query::Providers; use crate::util::nodemap::{NodeMap, FxHashSet}; use errors::FatalError; -use syntax_pos::{Span, DUMMY_SP, MultiSpan}; +use syntax_pos::{Span, DUMMY_SP, symbol::InternedString, MultiSpan}; use syntax::source_map::Spanned; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect}; use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy}; @@ -122,9 +122,9 @@ impl fmt::Display for HirId { // 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_index::vec::Idx; + use rustc_data_structures::indexed_vec::Idx; use rustc_macros::HashStable; - rustc_index::newtype_index! { + newtype_index! { /// An `ItemLocalId` uniquely identifies something within a given "item-like"; /// that is, within a `hir::Item`, `hir::TraitItem`, or `hir::ImplItem`. There is no /// guarantee that the numerical value of a given `ItemLocalId` corresponds to @@ -628,9 +628,9 @@ impl Generics { own_counts } - pub fn get_named(&self, name: Symbol) -> Option<&GenericParam> { + pub fn get_named(&self, name: InternedString) -> Option<&GenericParam> { for param in &self.params { - if name == param.name.ident().name { + if name == param.name.ident().as_interned_str() { return Some(param); } } @@ -669,12 +669,6 @@ impl WhereClause { Some(self.span) } } - - /// The `WhereClause` under normal circumstances points at either the predicates or the empty - /// space where the `where` clause should be. Only of use for diagnostic suggestions. - pub fn span_for_predicates_or_empty_place(&self) -> Span { - self.span - } } /// A single predicate in a where-clause. @@ -867,7 +861,7 @@ pub struct Block { pub span: Span, /// If true, then there may exist `break 'a` values that aim to /// break out of this block early. - /// Used by `'label: {}` blocks and by `try {}` blocks. + /// Used by `'label: {}` blocks and by `catch` statements. pub targeted_by_break: bool, } @@ -995,15 +989,6 @@ pub enum RangeEnd { Excluded, } -impl fmt::Display for RangeEnd { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(match self { - RangeEnd::Included => "..=", - RangeEnd::Excluded => "..", - }) - } -} - #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum PatKind { /// Represents a wildcard pattern (i.e., `_`). @@ -1068,16 +1053,9 @@ impl Mutability { MutImmutable => MutImmutable, } } - - pub fn invert(self) -> Self { - match self { - MutMutable => MutImmutable, - MutImmutable => MutMutable, - } - } } -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)] pub enum BinOpKind { /// The `+` operator (addition). Add, @@ -1211,7 +1189,7 @@ impl Into for BinOpKind { pub type BinOp = Spanned; -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)] pub enum UnOp { /// The `*` operator (deferencing). UnDeref, @@ -1381,54 +1359,24 @@ impl Body { hir_id: self.value.hir_id, } } - - pub fn generator_kind(&self) -> Option { - self.generator_kind - } } /// The type of source expression that caused this generator to be created. -#[derive(Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable, Debug, Copy)] +// Not `IsAsync` because we want to eventually add support for `AsyncGen` +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, + RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum GeneratorKind { - /// An explicit `async` block or the body of an async function. - Async(AsyncGeneratorKind), - + /// An `async` block or function. + Async, /// A generator literal created via a `yield` inside a closure. Gen, } impl fmt::Display for GeneratorKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - GeneratorKind::Async(k) => fmt::Display::fmt(k, f), - GeneratorKind::Gen => f.write_str("generator"), - } - } -} - -/// In the case of a generator created as part of an async construct, -/// which kind of async construct caused it to be created? -/// -/// This helps error messages but is also used to drive coercions in -/// type-checking (see #60424). -#[derive(Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable, Debug, Copy)] -pub enum AsyncGeneratorKind { - /// An explicit `async` block written by the user. - Block, - - /// An explicit `async` block written by the user. - Closure, - - /// The `async` block generated as the body of an async function. - Fn, -} - -impl fmt::Display for AsyncGeneratorKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match self { - AsyncGeneratorKind::Block => "`async` block", - AsyncGeneratorKind::Closure => "`async` closure body", - AsyncGeneratorKind::Fn => "`async fn` body", + GeneratorKind::Async => "`async` object", + GeneratorKind::Gen => "generator", }) } } @@ -1572,19 +1520,6 @@ impl Expr { } } } - - /// If `Self.kind` is `ExprKind::DropTemps(expr)`, drill down until we get a non-`DropTemps` - /// `Expr`. This is used in suggestions to ignore this `ExprKind` as it is semantically - /// silent, only signaling the ownership system. By doing this, suggestions that check the - /// `ExprKind` of any given `Expr` for presentation don't have to care about `DropTemps` - /// beyond remembering to call this function before doing analysis on it. - pub fn peel_drop_temps(&self) -> &Self { - let mut expr = self; - while let ExprKind::DropTemps(inner) = &expr.kind { - expr = inner; - } - expr - } } impl fmt::Debug for Expr { @@ -1823,7 +1758,6 @@ pub struct Destination { pub enum GeneratorMovability { /// May contain self-references, `!Unpin`. Static, - /// Must not contain self-references, `Unpin`. Movable, } @@ -2082,6 +2016,9 @@ pub enum TyKind { Infer, /// Placeholder for a type that has failed to be defined. Err, + /// Placeholder for C-variadic arguments. We "spoof" the `VaListImpl` created + /// from the variadic arguments. This type is only valid up to typeck. + CVarArgs(Lifetime), } #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] @@ -2706,11 +2643,6 @@ pub struct CodegenFnAttrs { /// probably isn't set when this is set, this is for foreign items while /// `#[export_name]` is for Rust-defined functions. pub link_name: Option, - /// The `#[link_ordinal = "..."]` attribute, indicating an ordinal an - /// imported function has in the dynamic library. Note that this must not - /// be set when `link_name` is set. This is for foreign items with the - /// "raw-dylib" kind. - pub link_ordinal: Option, /// The `#[target_feature(enable = "...")]` attribute and the enabled /// features (only enabled features are supported right now). pub target_features: Vec, @@ -2758,9 +2690,7 @@ bitflags! { const USED = 1 << 9; /// #[ffi_returns_twice], indicates that an extern function can return /// multiple times - const FFI_RETURNS_TWICE = 1 << 10; - /// #[track_caller]: allow access to the caller location - const TRACK_CALLER = 1 << 11; + const FFI_RETURNS_TWICE = 1 << 10; } } @@ -2772,7 +2702,6 @@ impl CodegenFnAttrs { optimize: OptimizeAttr::None, export_name: None, link_name: None, - link_ordinal: None, target_features: vec![], linkage: None, link_section: None, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index b852098d4cef7..91f2c5a0aaf85 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1,10 +1,10 @@ use rustc_target::spec::abi::Abi; use syntax::ast; use syntax::source_map::{SourceMap, Spanned}; +use syntax::parse::ParseSess; use syntax::print::pp::{self, Breaks}; use syntax::print::pp::Breaks::{Consistent, Inconsistent}; use syntax::print::pprust::{self, Comments, PrintState}; -use syntax::sess::ParseSess; use syntax::symbol::kw; use syntax::util::parser::{self, AssocOp, Fixity}; use syntax_pos::{self, BytePos, FileName}; @@ -361,6 +361,9 @@ impl<'a> State<'a> { self.s.word("/*ERROR*/"); self.pclose(); } + hir::TyKind::CVarArgs(_) => { + self.s.word("..."); + } } self.end() } diff --git a/src/librustc/hir/ptr.rs b/src/librustc/hir/ptr.rs index 7ee461a859bd6..1976b4c9e54ff 100644 --- a/src/librustc/hir/ptr.rs +++ b/src/librustc/hir/ptr.rs @@ -9,9 +9,10 @@ use std::{slice, vec}; use rustc_serialize::{Encodable, Decodable, Encoder, Decoder}; -use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; +use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, + HashStable}; /// An owned smart pointer. -#[derive(PartialEq, Eq)] +#[derive(Hash, PartialEq, Eq)] pub struct P { ptr: Box } @@ -132,7 +133,9 @@ impl Decodable for P<[T]> { impl HashStable for P where T: ?Sized + HashStable { - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut CTX, + hasher: &mut StableHasher) { (**self).hash_stable(hcx, hasher); } } diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 14d0673ecc03f..182a9ade8c36e 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -13,14 +13,14 @@ use std::cell::RefCell; use syntax::ast; use syntax::source_map::SourceMap; -use syntax_expand::hygiene::SyntaxContext; +use syntax::ext::hygiene::SyntaxContext; use syntax::symbol::Symbol; use syntax::tokenstream::DelimSpan; use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::hygiene; use rustc_data_structures::stable_hasher::{ - HashStable, StableHasher, ToStableHashKey, + HashStable, StableHasher, StableHasherResult, ToStableHashKey, }; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use smallvec::SmallVec; @@ -219,7 +219,9 @@ impl<'a> StableHashingContextProvider<'a> for StableHashingContext<'a> { impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> {} impl<'a> HashStable> for hir::BodyId { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { if hcx.hash_bodies() { hcx.body_resolver.body(*self).hash_stable(hcx, hasher); } @@ -228,7 +230,9 @@ impl<'a> HashStable> for hir::BodyId { impl<'a> HashStable> for hir::HirId { #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { match hcx.node_id_hashing_mode { NodeIdHashingMode::Ignore => { // Don't do anything. @@ -259,7 +263,9 @@ impl<'a> ToStableHashKey> for hir::HirId { } impl<'a> HashStable> for ast::NodeId { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { match hcx.node_id_hashing_mode { NodeIdHashingMode::Ignore => { // Don't do anything. @@ -292,7 +298,9 @@ impl<'a> HashStable> for Span { /// 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) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { const TAG_VALID_SPAN: u8 = 0; const TAG_INVALID_SPAN: u8 = 1; const TAG_EXPANSION: u8 = 0; @@ -371,18 +379,24 @@ impl<'a> HashStable> for Span { } impl<'a> HashStable> for DelimSpan { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher, + ) { self.open.hash_stable(hcx, hasher); self.close.hash_stable(hcx, hasher); } } -pub fn hash_stable_trait_impls<'a>( +pub fn hash_stable_trait_impls<'a, W>( hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher, + hasher: &mut StableHasher, blanket_impls: &[DefId], non_blanket_impls: &FxHashMap>, -) { +) where + W: StableHasherResult, +{ { let mut blanket_impls: SmallVec<[_; 8]> = blanket_impls .iter() diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index c0255e5b8a481..8e74f1e11eb51 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -6,7 +6,9 @@ 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}; +use rustc_data_structures::stable_hasher::{ + HashStable, ToStableHashKey, StableHasher, StableHasherResult, +}; use smallvec::SmallVec; use std::mem; use syntax::ast; @@ -14,7 +16,9 @@ use syntax::attr; impl<'a> HashStable> for DefId { #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { hcx.def_path_hash(*self).hash_stable(hcx, hasher); } } @@ -30,7 +34,9 @@ impl<'a> ToStableHashKey> for DefId { impl<'a> HashStable> for LocalDefId { #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { hcx.def_path_hash(self.to_def_id()).hash_stable(hcx, hasher); } } @@ -46,7 +52,9 @@ impl<'a> ToStableHashKey> for LocalDefId { impl<'a> HashStable> for CrateNum { #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { hcx.def_path_hash(DefId { krate: *self, index: CRATE_DEF_INDEX @@ -84,7 +92,9 @@ for hir::ItemLocalId { // in "DefPath Mode". impl<'a> HashStable> for hir::ItemId { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let hir::ItemId { id } = *self; @@ -96,7 +106,9 @@ impl<'a> HashStable> for hir::ItemId { } impl<'a> HashStable> for hir::TraitItemId { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let hir::TraitItemId { hir_id } = * self; @@ -108,7 +120,9 @@ impl<'a> HashStable> for hir::TraitItemId { } impl<'a> HashStable> for hir::ImplItemId { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let hir::ImplItemId { hir_id } = * self; @@ -124,7 +138,9 @@ impl_stable_hash_for!(struct ast::Label { }); impl<'a> HashStable> for hir::Ty { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { hcx.while_hashing_hir_bodies(true, |hcx| { let hir::Ty { hir_id: _, @@ -150,7 +166,9 @@ impl_stable_hash_for!(struct hir::Stmt { impl_stable_hash_for_spanned!(ast::Name); impl<'a> HashStable> for hir::Expr { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { hcx.while_hashing_hir_bodies(true, |hcx| { let hir::Expr { hir_id: _, @@ -174,7 +192,9 @@ impl_stable_hash_for!(struct ast::Ident { }); impl<'a> HashStable> for hir::TraitItem { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let hir::TraitItem { hir_id: _, ident, @@ -196,7 +216,9 @@ impl<'a> HashStable> for hir::TraitItem { impl<'a> HashStable> for hir::ImplItem { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let hir::ImplItem { hir_id: _, ident, @@ -226,7 +248,9 @@ impl_stable_hash_for!(enum ast::CrateSugar { }); impl<'a> HashStable> for hir::VisibilityKind { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { hir::VisibilityKind::Public | @@ -249,7 +273,9 @@ impl<'a> HashStable> for hir::VisibilityKind { impl_stable_hash_for_spanned!(hir::VisibilityKind); impl<'a> HashStable> for hir::Mod { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let hir::Mod { inner: ref inner_span, ref item_ids, @@ -279,7 +305,9 @@ impl_stable_hash_for_spanned!(hir::Variant); impl<'a> HashStable> for hir::Item { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let hir::Item { ident, ref attrs, @@ -300,7 +328,9 @@ impl<'a> HashStable> for hir::Item { } impl<'a> HashStable> for hir::Body { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let hir::Body { params, value, @@ -329,7 +359,9 @@ impl<'a> ToStableHashKey> for hir::BodyId { impl<'a> HashStable> for hir::def_id::DefIndex { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { hcx.local_def_path_hash(*self).hash_stable(hcx, hasher); } } @@ -344,13 +376,17 @@ impl<'a> ToStableHashKey> for hir::def_id::DefIndex { } impl<'a> HashStable> for crate::middle::lang_items::LangItem { - fn hash_stable(&self, _: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + _: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { ::std::hash::Hash::hash(self, hasher); } } impl<'a> HashStable> for hir::TraitCandidate { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { let hir::TraitCandidate { def_id, @@ -382,13 +418,17 @@ impl<'a> ToStableHashKey> for hir::TraitCandidate { } impl<'hir> HashStable> for attr::InlineAttr { - fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'hir>, + hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); } } impl<'hir> HashStable> for attr::OptimizeAttr { - fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'hir>, + hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); } } diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 2510d7efb59e7..91c6c968f9853 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -9,49 +9,53 @@ use std::mem; use syntax::ast; use syntax::feature_gate; use syntax::parse::token; -use syntax::symbol::LocalInternedString; +use syntax::symbol::InternedString; use syntax::tokenstream; use syntax_pos::SourceFile; use crate::hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX}; use smallvec::SmallVec; -use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, + StableHasher, StableHasherResult}; -impl<'a> HashStable> for LocalInternedString { +impl<'a> HashStable> for InternedString { #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let str = self as &str; - str.hash_stable(hcx, hasher) + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { + self.with(|s| s.hash_stable(hcx, hasher)) } } -impl<'a> ToStableHashKey> for LocalInternedString { - type KeyType = LocalInternedString; +impl<'a> ToStableHashKey> for InternedString { + type KeyType = InternedString; #[inline] fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) - -> LocalInternedString { + -> InternedString { self.clone() } } impl<'a> HashStable> for ast::Name { #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { self.as_str().hash_stable(hcx, hasher); } } impl<'a> ToStableHashKey> for ast::Name { - type KeyType = LocalInternedString; + type KeyType = InternedString; #[inline] fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) - -> LocalInternedString { - self.as_str() + -> InternedString { + self.as_interned_str() } } @@ -60,7 +64,7 @@ impl_stable_hash_for!(enum ::syntax::ast::AsmDialect { Intel }); -impl_stable_hash_for!(enum ::syntax_expand::base::MacroKind { +impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind { Bang, Attr, Derive, @@ -106,7 +110,9 @@ impl_stable_hash_for!(enum ::syntax::edition::Edition { impl<'a> HashStable> for ::syntax::attr::StabilityLevel { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue, ref is_soft } => { @@ -166,7 +172,9 @@ impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) }); impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner }); impl<'a> HashStable> for [ast::Attribute] { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { if self.len() == 0 { self.len().hash_stable(hcx, hasher); return @@ -189,7 +197,9 @@ impl<'a> HashStable> for [ast::Attribute] { } impl<'a> HashStable> for ast::Path { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { self.segments.len().hash_stable(hcx, hasher); for segment in &self.segments { segment.ident.name.hash_stable(hcx, hasher); @@ -197,34 +207,37 @@ impl<'a> HashStable> for ast::Path { } } -impl_stable_hash_for!(struct ::syntax::ast::AttrItem { - path, - tokens, -}); - impl<'a> HashStable> for ast::Attribute { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { // Make sure that these have been filtered out. debug_assert!(!self.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name))); debug_assert!(!self.is_sugared_doc); let ast::Attribute { - ref item, id: _, style, + ref path, + ref tokens, is_sugared_doc: _, span, } = *self; - item.hash_stable(hcx, hasher); style.hash_stable(hcx, hasher); + path.hash_stable(hcx, hasher); + for tt in tokens.trees() { + tt.hash_stable(hcx, hasher); + } span.hash_stable(hcx, hasher); } } impl<'a> HashStable> for tokenstream::TokenTree { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { tokenstream::TokenTree::Token(ref token) => { @@ -243,7 +256,9 @@ for tokenstream::TokenTree { impl<'a> HashStable> for tokenstream::TokenStream { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { for sub_tt in self.trees() { sub_tt.hash_stable(hcx, hasher); } @@ -270,7 +285,9 @@ impl_stable_hash_for!(struct token::Lit { }); impl<'a> HashStable> for token::TokenKind { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { token::Eq | @@ -409,7 +426,9 @@ impl_stable_hash_for!(enum ::syntax_pos::FileName { }); impl<'a> HashStable> for SourceFile { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { let SourceFile { name: _, // We hash the smaller name_hash instead of this name_hash, @@ -425,7 +444,6 @@ impl<'a> HashStable> for SourceFile { ref lines, ref multibyte_chars, ref non_narrow_chars, - ref normalized_pos, } = *self; (name_hash as u64).hash_stable(hcx, hasher); @@ -454,12 +472,6 @@ impl<'a> HashStable> for SourceFile { for &char_pos in non_narrow_chars.iter() { stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher); } - - normalized_pos.len().hash_stable(hcx, hasher); - for &char_pos in normalized_pos.iter() { - stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher); - } - } } @@ -489,20 +501,12 @@ fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar, (pos.0 - source_file_start.0, width as u32) } -fn stable_normalized_pos(np: ::syntax_pos::NormalizedPos, - source_file_start: ::syntax_pos::BytePos) - -> (u32, u32) { - let ::syntax_pos::NormalizedPos { - pos, - diff - } = np; - - (pos.0 - source_file_start.0, diff) -} - - impl<'tcx> HashStable> for feature_gate::Features { - fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'tcx>, + hasher: &mut StableHasher, + ) { // Unfortunately we cannot exhaustively list fields here, since the // struct is macro generated. self.declared_lang_features.hash_stable(hcx, hasher); diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index c643baf11254c..56b1560772997 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -3,7 +3,8 @@ use crate::ich::{Fingerprint, StableHashingContext, NodeIdHashingMode}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, + StableHasher, StableHasherResult}; use std::cell::RefCell; use std::mem; use crate::middle::region; @@ -14,7 +15,9 @@ impl<'a, 'tcx, T> HashStable> for &'tcx ty::List where T: HashStable>, { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { thread_local! { static CACHE: RefCell> = RefCell::new(Default::default()); @@ -54,14 +57,18 @@ where } impl<'a, 'tcx> HashStable> for ty::subst::GenericArg<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { self.unpack().hash_stable(hcx, hasher); } } impl<'a> HashStable> for ty::RegionKind { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { ty::ReErased | @@ -105,21 +112,31 @@ for ty::RegionKind { impl<'a> HashStable> for ty::RegionVid { #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { self.index().hash_stable(hcx, hasher); } } impl<'a, 'tcx> HashStable> for ty::ConstVid<'tcx> { #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher, + ) { self.index.hash_stable(hcx, hasher); } } impl<'tcx> HashStable> for ty::BoundVar { #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'tcx>, + hasher: &mut StableHasher, + ) { self.index().hash_stable(hcx, hasher); } } @@ -128,14 +145,20 @@ impl<'a, T> HashStable> for ty::Binder where T: HashStable>, { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { self.skip_binder().hash_stable(hcx, hasher); } } // AllocIds get resolved to whatever they point to (to be stable) impl<'a> HashStable> for mir::interpret::AllocId { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher, + ) { ty::tls::with_opt(|tcx| { trace!("hashing {:?}", *self); let tcx = tcx.expect("can't hash AllocIds during hir lowering"); @@ -151,7 +174,11 @@ for mir::interpret::Relocations where Tag: HashStable>, { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher, + ) { self.len().hash_stable(hcx, hasher); for reloc in self.iter() { reloc.hash_stable(hcx, hasher); @@ -174,7 +201,9 @@ impl<'a> ToStableHashKey> for region::Scope { } impl<'a> HashStable> for ty::TyVid { - fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { + fn hash_stable(&self, + _hcx: &mut StableHashingContext<'a>, + _hasher: &mut StableHasher) { // `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) @@ -182,7 +211,9 @@ impl<'a> HashStable> for ty::TyVid { } impl<'a> HashStable> for ty::IntVid { - fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { + fn hash_stable(&self, + _hcx: &mut StableHashingContext<'a>, + _hasher: &mut StableHasher) { // `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) @@ -190,7 +221,9 @@ impl<'a> HashStable> for ty::IntVid { } impl<'a> HashStable> for ty::FloatVid { - fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { + fn hash_stable(&self, + _hcx: &mut StableHashingContext<'a>, + _hasher: &mut StableHasher) { // `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) @@ -201,14 +234,18 @@ impl<'a, T> HashStable> for ty::steal::Steal where T: HashStable>, { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { self.borrow().hash_stable(hcx, hasher); } } impl<'a> HashStable> for crate::middle::privacy::AccessLevels { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { let crate::middle::privacy::AccessLevels { ref map diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 49a2c90bdbf60..2ea1317a94fd9 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -18,7 +18,7 @@ use crate::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags}; use crate::ty::flags::FlagComputation; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::Idx; +use rustc_data_structures::indexed_vec::Idx; use smallvec::SmallVec; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { @@ -468,7 +468,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { ConstValue::Infer(InferConst::Fresh(_)) => { bug!("encountered a fresh const during canonicalization") } - ConstValue::Bound(debruijn, _) => { + ConstValue::Infer(InferConst::Canonical(debruijn, _)) => { if debruijn >= self.binder_index { bug!("escaping bound type during canonicalization") } else { @@ -700,8 +700,8 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { let var = self.canonical_var(info, const_var.into()); self.tcx().mk_const( ty::Const { - val: ConstValue::Bound(self.binder_index, var.into()), - ty: self.fold_ty(const_var.ty), + val: ConstValue::Infer(InferConst::Canonical(self.binder_index, var.into())), + ty: const_var.ty, } ) } diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index d833feeeb09d6..4e442608f0e7e 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -25,7 +25,7 @@ use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVari use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind}; use crate::infer::region_constraints::MemberConstraint; use crate::mir::interpret::ConstValue; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_macros::HashStable; use rustc_serialize::UseSpecializedDecodable; use smallvec::SmallVec; @@ -33,7 +33,7 @@ use std::ops::Index; use syntax::source_map::Span; use crate::ty::fold::TypeFoldable; use crate::ty::subst::GenericArg; -use crate::ty::{self, BoundVar, Lift, List, Region, TyCtxt}; +use crate::ty::{self, BoundVar, InferConst, Lift, List, Region, TyCtxt}; mod canonicalizer; @@ -73,7 +73,7 @@ pub struct CanonicalVarValues<'tcx> { /// various parts of it with canonical variables. This struct stores /// those replaced bits to remember for when we process the query /// result. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)] pub struct OriginalQueryValues<'tcx> { /// Map from the universes that appear in the query to the /// universes in the caller context. For the time being, we only @@ -510,7 +510,9 @@ impl<'tcx> CanonicalVarValues<'tcx> { GenericArgKind::Const(ct) => { tcx.mk_const(ty::Const { ty: ct.ty, - val: ConstValue::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)), + val: ConstValue::Infer( + InferConst::Canonical(ty::INNERMOST, ty::BoundVar::from_u32(i)) + ), }).into() } }) diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 7ad6006012f49..18c1b41d5bb4c 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -17,8 +17,8 @@ use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::InferCtxtBuilder; use crate::infer::{InferCtxt, InferOk, InferResult}; use crate::mir::interpret::ConstValue; -use rustc_index::vec::Idx; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::indexed_vec::IndexVec; use std::fmt::Debug; use syntax_pos::DUMMY_SP; use crate::traits::query::{Fallible, NoSolution}; @@ -26,7 +26,7 @@ use crate::traits::TraitEngine; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use crate::ty::fold::TypeFoldable; use crate::ty::subst::{GenericArg, GenericArgKind}; -use crate::ty::{self, BoundVar, Ty, TyCtxt}; +use crate::ty::{self, BoundVar, InferConst, Ty, TyCtxt}; use crate::util::captures::Captures; impl<'tcx> InferCtxtBuilder<'tcx> { @@ -493,7 +493,10 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { } } GenericArgKind::Const(result_value) => { - if let ty::Const { val: ConstValue::Bound(debrujin, b), .. } = result_value { + if let ty::Const { + val: ConstValue::Infer(InferConst::Canonical(debrujin, b)), + .. + } = result_value { // ...in which case we would set `canonical_vars[0]` to `Some(const X)`. // We only allow a `ty::INNERMOST` index in substitutions. diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 51ae4e49493f7..6f73275d455f5 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -53,7 +53,7 @@ pub struct CombineFields<'infcx, 'tcx> { pub obligations: PredicateObligations<'tcx>, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum RelationDir { SubtypeOf, SupertypeOf, EqTo } @@ -494,7 +494,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { if sub_vid == self.for_vid_sub_root { // If sub-roots are equal, then `for_vid` and // `vid` are related via subtyping. - Err(TypeError::CyclicTy(self.root_ty)) + return Err(TypeError::CyclicTy(self.root_ty)); } else { match variables.probe(vid) { TypeVariableValue::Known { value: u } => { @@ -527,7 +527,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { let u = self.tcx().mk_ty_var(new_var_id); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); - Ok(u) + return Ok(u); } } } @@ -602,26 +602,19 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be == - match c.val { - ConstValue::Infer(InferConst::Var(vid)) => { + match c { + ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } => { let mut variable_table = self.infcx.const_unification_table.borrow_mut(); - let var_value = variable_table.probe_value(vid); - match var_value.val { - ConstVariableValue::Known { value: u } => self.relate(&u, &u), - ConstVariableValue::Unknown { universe } => { - if self.for_universe.can_name(universe) { - Ok(c) - } else { - let new_var_id = variable_table.new_key(ConstVarValue { - origin: var_value.origin, - val: ConstVariableValue::Unknown { universe: self.for_universe }, - }); - Ok(self.tcx().mk_const_var(new_var_id, c.ty)) - } + match variable_table.probe_value(*vid).val.known() { + Some(u) => { + self.relate(&u, &u) } + None => Ok(c), } } - _ => relate::super_relate_consts(self, c, c), + _ => { + relate::super_relate_consts(self, c, c) + } } } } diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index a50cc86862e57..d31b527a55b69 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -200,7 +200,7 @@ impl<'tcx> TyCtxt<'tcx> { { sp = param.span; } - (format!("the lifetime `{}` as defined on", br.name), sp) + (format!("the lifetime {} as defined on", br.name), sp) } ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegion::BrNamed(_, name), @@ -213,7 +213,7 @@ impl<'tcx> TyCtxt<'tcx> { { sp = param.span; } - (format!("the lifetime `{}` as defined on", name), sp) + (format!("the lifetime {} as defined on", name), sp) } ty::ReFree(ref fr) => match fr.bound_region { ty::BrAnon(idx) => ( @@ -221,7 +221,7 @@ impl<'tcx> TyCtxt<'tcx> { self.hir().span(node), ), _ => ( - format!("the lifetime `{}` as defined on", region), + format!("the lifetime {} as defined on", region), cm.def_span(self.hir().span(node)), ), }, @@ -542,7 +542,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { disambiguated_data: &DisambiguatedDefPathData, ) -> Result { let mut path = print_prefix(self)?; - path.push(disambiguated_data.data.as_symbol().to_string()); + path.push(disambiguated_data.data.as_interned_str().to_string()); Ok(path) } fn path_generic_args( @@ -935,7 +935,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .filter(|(a, b)| a == b) .count(); let len = sub1.len() - common_default_params; - let consts_offset = len - sub1.consts().count(); // Only draw `<...>` if there're lifetime/type arguments. if len > 0 { @@ -982,8 +981,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // ^ elided type as this type argument was the same in both sides let type_arguments = sub1.types().zip(sub2.types()); let regions_len = sub1.regions().count(); - let num_display_types = consts_offset - regions_len; - for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() { + for (i, (ta1, ta2)) in type_arguments.take(len).enumerate() { let i = i + regions_len; if ta1 == ta2 { values.0.push_normal("_"); @@ -996,21 +994,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.push_comma(&mut values.0, &mut values.1, len, i); } - // Do the same for const arguments, if they are equal, do not highlight and - // elide them from the output. - let const_arguments = sub1.consts().zip(sub2.consts()); - for (i, (ca1, ca2)) in const_arguments.enumerate() { - let i = i + consts_offset; - if ca1 == ca2 { - values.0.push_normal("_"); - values.1.push_normal("_"); - } else { - values.0.push_highlighted(ca1.to_string()); - values.1.push_highlighted(ca2.to_string()); - } - self.push_comma(&mut values.0, &mut values.1, len, i); - } - // Close the type argument bracket. // Only draw `<...>` if there're lifetime/type arguments. if len > 0 { @@ -1146,17 +1129,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let span = cause.span(self.tcx); - // Ignore msg for object safe coercion - // since E0038 message will be printed - match terr { - TypeError::ObjectUnsafeCoercion(_) => {} - _ => { - diag.span_label(span, terr.to_string()); - if let Some((sp, msg)) = secondary_span { - diag.span_label(sp, msg); - } - } - }; + diag.span_label(span, terr.to_string()); + if let Some((sp, msg)) = secondary_span { + diag.span_label(sp, msg); + } if let Some((expected, found)) = expected_found { match (terr, is_simple_error, expected == found) { @@ -1176,9 +1152,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &sort_string(values.found), ); } - (TypeError::ObjectUnsafeCoercion(_), ..) => { - diag.note_unsuccessfull_coercion(found, expected); - } (_, false, _) => { if let Some(exp_found) = exp_found { self.suggest_as_ref_where_appropriate(span, &exp_found, diag); @@ -1277,10 +1250,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let span = trace.cause.span(self.tcx); let failure_code = trace.cause.as_failure_code(terr); let mut diag = match failure_code { - FailureCode::Error0038(did) => { - let violations = self.tcx.object_safety_violations(did); - self.tcx.report_object_safety_error(span, did, violations) - } FailureCode::Error0317(failure_str) => { struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str) } @@ -1642,7 +1611,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } enum FailureCode { - Error0038(DefId), Error0317(&'static str), Error0580(&'static str), Error0308(&'static str), @@ -1681,7 +1649,6 @@ impl<'tcx> ObligationCause<'tcx> { TypeError::IntrinsicCast => { Error0308("cannot coerce intrinsics to function pointers") } - TypeError::ObjectUnsafeCoercion(did) => Error0038(did.clone()), _ => Error0308("mismatched types"), }, } diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index b89731273f7e2..1df60dfc63ef3 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -220,7 +220,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let ty_msg = match local_visitor.found_ty { Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => { - let fn_sig = substs.as_closure().sig(*def_id, self.tcx); + 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) @@ -255,7 +255,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let suffix = match local_visitor.found_ty { Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => { - let fn_sig = substs.as_closure().sig(*def_id, self.tcx); + 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 { diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 1841bd9ea6423..9e9220cc3d8cc 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -252,7 +252,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { return ct; } - ConstValue::Bound(..) | + ConstValue::Infer(ty::InferConst::Canonical(..)) | ConstValue::Placeholder(_) => { bug!("unexpected const {:?}", ct) } diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index f30f19d41509d..6282fde59cad4 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -19,8 +19,8 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::implementation::{ Direction, Graph, NodeIndex, INCOMING, OUTGOING, }; -use rustc_index::bit_set::BitSet; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use smallvec::SmallVec; use std::fmt; use syntax_pos::Span; @@ -304,7 +304,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) { - let mut process_constraint = |constraint: &Constraint<'tcx>| { + self.iterate_until_fixed_point("Expansion", |constraint| { + debug!("expansion: constraint={:?}", constraint); let (a_region, b_vid, b_data, retain) = match *constraint { Constraint::RegSubVar(a_region, b_vid) => { let b_data = var_values.value_mut(b_vid); @@ -330,33 +331,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let changed = self.expand_node(a_region, b_vid, b_data); (changed, retain) - }; - - // Using bitsets to track the remaining elements is faster than using a - // `Vec` by itself (which requires removing elements, which requires - // element shuffling, which is slow). - let constraints: Vec<_> = self.data.constraints.keys().collect(); - let mut live_indices: BitSet = BitSet::new_filled(constraints.len()); - let mut killed_indices: BitSet = BitSet::new_empty(constraints.len()); - let mut changed = true; - while changed { - changed = false; - for index in live_indices.iter() { - let constraint = constraints[index]; - let (edge_changed, retain) = process_constraint(constraint); - if edge_changed { - changed = true; - } - if !retain { - let changed = killed_indices.insert(index); - debug_assert!(changed); - } - } - live_indices.subtract(&killed_indices); - - // We could clear `killed_indices` here, but we don't need to and - // it's cheaper not to. - } + }) } // This function is very hot in some workloads. There's a single callsite @@ -385,21 +360,13 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { match *b_data { VarValue::Value(cur_region) => { // Identical scopes can show up quite often, if the fixed point - // iteration converges slowly. Skip them. This is purely an - // optimization. + // iteration converges slowly, skip them if let (ReScope(a_scope), ReScope(cur_scope)) = (a_region, cur_region) { if a_scope == cur_scope { return false; } } - // This is a specialized version of the `lub_concrete_regions` - // check below for a common case, here purely as an - // optimization. - if let ReEmpty = a_region { - return false; - } - let mut lub = self.lub_concrete_regions(a_region, cur_region); if lub == cur_region { return false; @@ -440,6 +407,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { /// Returns the smallest region `c` such that `a <= c` and `b <= c`. fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> { + let tcx = self.tcx(); + match (a, b) { (&ty::ReClosureBound(..), _) | (_, &ty::ReClosureBound(..)) @@ -499,7 +468,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // otherwise, we don't know what the free region is, // so we must conservatively say the LUB is static: - self.tcx().lifetimes.re_static + tcx.lifetimes.re_static } (&ReScope(a_id), &ReScope(b_id)) => { @@ -507,7 +476,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // subtype of the region corresponding to an inner // block. let lub = self.region_rels.region_scope_tree.nearest_common_ancestor(a_id, b_id); - self.tcx().mk_region(ReScope(lub)) + tcx.mk_region(ReScope(lub)) } (&ReEarlyBound(_), &ReEarlyBound(_)) @@ -521,7 +490,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { if a == b { a } else { - self.tcx().lifetimes.re_static + tcx.lifetimes.re_static } } } @@ -891,6 +860,29 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } + fn iterate_until_fixed_point(&self, tag: &str, mut body: F) + where + F: FnMut(&Constraint<'tcx>) -> (bool, bool), + { + let mut constraints: SmallVec<[_; 16]> = self.data.constraints.keys().collect(); + let mut iteration = 0; + let mut changed = true; + while changed { + changed = false; + iteration += 1; + debug!("---- {} Iteration {}{}", "#", tag, iteration); + constraints.retain(|constraint| { + let (edge_changed, retain) = body(constraint); + if edge_changed { + debug!("updated due to constraint {:?}", constraint); + changed = true; + } + retain + }); + } + debug!("---- {} Complete after {} iteration(s)", tag, iteration); + } + fn bound_is_met( &self, bound: &VerifyBound<'tcx>, diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index e385d576b8ceb..750ca4e32a64e 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -23,7 +23,7 @@ use crate::ty::relate::RelateResult; use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt, InferConst}; use crate::ty::{FloatVid, IntVid, TyVid, ConstVid}; -use crate::util::nodemap::{FxHashMap, FxHashSet}; +use crate::util::nodemap::FxHashMap; use errors::DiagnosticBuilder; use rustc_data_structures::sync::Lrc; @@ -32,7 +32,7 @@ use std::cell::{Cell, Ref, RefCell, RefMut}; use std::collections::BTreeMap; use std::fmt; use syntax::ast; -use syntax_pos::symbol::Symbol; +use syntax_pos::symbol::InternedString; use syntax_pos::Span; use self::combine::CombineFields; @@ -155,8 +155,6 @@ pub struct InferCtxt<'a, 'tcx> { /// avoid reporting the same error twice. pub reported_trait_errors: RefCell>>>, - pub reported_closure_mismatch: RefCell)>>, - /// When an error occurs, we want to avoid reporting "derived" /// errors that are due to this original failure. Normally, we /// handle this with the `err_count_on_creation` count, which @@ -392,7 +390,7 @@ pub enum RegionVariableOrigin { Coercion(Span), /// Region variables created as the values for early-bound regions - EarlyBoundRegion(Span, Symbol), + EarlyBoundRegion(Span, InternedString), /// Region variables created for bound regions /// in a function or method that is called @@ -407,7 +405,7 @@ pub enum RegionVariableOrigin { NLL(NLLRegionVariableOrigin), } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum NLLRegionVariableOrigin { /// During NLL region processing, we create variables for free /// regions that we encounter in the function signature and @@ -418,19 +416,7 @@ pub enum NLLRegionVariableOrigin { /// from a `for<'a> T` binder). Meant to represent "any region". Placeholder(ty::PlaceholderRegion), - Existential { - /// If this is true, then this variable was created to represent a lifetime - /// bound in a `for` binder. For example, it might have been created to - /// represent the lifetime `'a` in a type like `for<'a> fn(&'a u32)`. - /// Such variables are created when we are trying to figure out if there - /// is any valid instantiation of `'a` that could fit into some scenario. - /// - /// This is used to inform error reporting: in the case that we are trying to - /// determine whether there is any valid instantiation of a `'a` variable that meets - /// some constraint C, we want to blame the "source" of that `for` type, - /// rather than blaming the source of the constraint C. - from_forall: bool - }, + Existential, } impl NLLRegionVariableOrigin { @@ -438,7 +424,7 @@ impl NLLRegionVariableOrigin { match self { NLLRegionVariableOrigin::FreeRegion => true, NLLRegionVariableOrigin::Placeholder(..) => true, - NLLRegionVariableOrigin::Existential{ .. } => false, + NLLRegionVariableOrigin::Existential => false, } } @@ -552,7 +538,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> { selection_cache: Default::default(), evaluation_cache: Default::default(), reported_trait_errors: Default::default(), - reported_closure_mismatch: Default::default(), tainted_by_errors_flag: Cell::new(false), err_count_on_creation: tcx.sess.err_count(), in_snapshot: Cell::new(false), @@ -814,16 +799,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Executes `f` and commit the bindings. pub fn commit_unconditionally(&self, f: F) -> R where - F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R, + F: FnOnce() -> R, { - debug!("commit_unconditionally()"); + debug!("commit()"); let snapshot = self.start_snapshot(); - let r = f(&snapshot); + let r = f(); self.commit_from(snapshot); r } - /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`. + /// Executes `f` and commit the bindings if closure `f` returns `Ok(_)`. pub fn commit_if_ok(&self, f: F) -> Result where F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result, @@ -843,7 +828,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { r } - /// Execute `f` then unroll any bindings it creates. + /// Execute `f` in a snapshot, and commit the bindings it creates. + pub fn in_snapshot(&self, f: F) -> T + where + F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> T, + { + debug!("in_snapshot()"); + let snapshot = self.start_snapshot(); + let r = f(&snapshot); + self.commit_from(snapshot); + r + } + + /// Executes `f` then unroll any bindings it creates. pub fn probe(&self, f: F) -> R where F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R, @@ -1307,14 +1304,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - /// Resolve any type variables found in `value` -- but only one - /// level. So, if the variable `?X` is bound to some type - /// `Foo`, then this would return `Foo` (but `?Y` may - /// itself be bound to a type). - /// - /// Useful when you only need to inspect the outermost level of - /// the type and don't care about nested types (or perhaps you - /// will be resolving them as well, e.g. in a loop). pub fn shallow_resolve(&self, value: T) -> T where T: TypeFoldable<'tcx>, @@ -1492,9 +1481,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn closure_kind( &self, closure_def_id: DefId, - closure_substs: SubstsRef<'tcx>, + closure_substs: ty::ClosureSubsts<'tcx>, ) -> Option { - let closure_kind_ty = closure_substs.as_closure().kind_ty(closure_def_id, self.tcx); + let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx); let closure_kind_ty = self.shallow_resolve(closure_kind_ty); closure_kind_ty.to_opt_closure_kind() } @@ -1506,9 +1495,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn closure_sig( &self, def_id: DefId, - substs: SubstsRef<'tcx>, + substs: ty::ClosureSubsts<'tcx>, ) -> ty::PolyFnSig<'tcx> { - let closure_sig_ty = substs.as_closure().sig_ty(def_id, self.tcx); + let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx); let closure_sig_ty = self.shallow_resolve(closure_sig_ty); closure_sig_ty.fn_sig(self.tcx) } @@ -1575,9 +1564,6 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> { ShallowResolver { infcx } } - /// If `typ` is a type variable of some kind, resolve it one level - /// (but do not resolve types found in the result). If `typ` is - /// not a type variable, just return it unmodified. pub fn shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> { match typ.kind { ty::Infer(ty::TyVar(v)) => { diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index d6f76e9ee346c..47e5c2b59ef36 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -28,12 +28,11 @@ use crate::ty::fold::{TypeFoldable, TypeVisitor}; use crate::ty::relate::{self, Relate, RelateResult, TypeRelation}; use crate::ty::subst::GenericArg; use crate::ty::{self, Ty, TyCtxt, InferConst}; -use crate::infer::{ConstVariableValue, ConstVarValue}; use crate::mir::interpret::ConstValue; use rustc_data_structures::fx::FxHashMap; use std::fmt::Debug; -#[derive(PartialEq)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum NormalizationStrategy { Lazy, Eager, @@ -94,7 +93,7 @@ pub trait TypeRelatingDelegate<'tcx> { /// we will invoke this method to instantiate `'a` with an /// inference variable (though `'b` would be instantiated first, /// as a placeholder). - fn next_existential_region_var(&mut self, was_placeholder: bool) -> ty::Region<'tcx>; + fn next_existential_region_var(&mut self) -> ty::Region<'tcx>; /// Creates a new region variable representing a /// higher-ranked region that is instantiated universally. @@ -194,7 +193,7 @@ where let placeholder = ty::PlaceholderRegion { universe, name: br }; delegate.next_placeholder_region(placeholder) } else { - delegate.next_existential_region_var(true) + delegate.next_existential_region_var() } } }; @@ -325,7 +324,7 @@ where let vid = pair.vid(); let value_ty = pair.value_ty(); - // FIXME(invariance) -- this logic assumes invariance, but that is wrong. + // FIXME -- this logic assumes invariance, but that is wrong. // This only presently applies to chalk integration, as NLL // doesn't permit type variables to appear on both sides (and // doesn't use lazy norm). @@ -617,21 +616,15 @@ where fn consts( &mut self, a: &'tcx ty::Const<'tcx>, - mut b: &'tcx ty::Const<'tcx>, + b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - let a = self.infcx.shallow_resolve(a); - - if !D::forbid_inference_vars() { - b = self.infcx.shallow_resolve(b); - } - - match b.val { - ConstValue::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => { - // Forbid inference variables in the RHS. - bug!("unexpected inference var {:?}", b) - } - // FIXME(invariance): see the related FIXME above. - _ => self.infcx.super_combine_consts(self, a, b) + if let ty::Const { val: ConstValue::Infer(InferConst::Canonical(_, _)), .. } = a { + // FIXME(const_generics): I'm unsure how this branch should actually be handled, + // so this is probably not correct. + self.infcx.super_combine_consts(self, a, b) + } else { + debug!("consts(a={:?}, b={:?}, variance={:?})", a, b, self.ambient_variance); + relate::super_relate_consts(self, a, b) } } @@ -998,28 +991,15 @@ where a: &'tcx ty::Const<'tcx>, _: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - match a.val { - ConstValue::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => { - bug!( - "unexpected inference variable encountered in NLL generalization: {:?}", - a - ); - } - ConstValue::Infer(InferConst::Var(vid)) => { - let mut variable_table = self.infcx.const_unification_table.borrow_mut(); - let var_value = variable_table.probe_value(vid); - match var_value.val.known() { - Some(u) => self.relate(&u, &u), - None => { - let new_var_id = variable_table.new_key(ConstVarValue { - origin: var_value.origin, - val: ConstVariableValue::Unknown { universe: self.universe }, - }); - Ok(self.tcx().mk_const_var(new_var_id, a.ty)) - } - } - } - _ => relate::super_relate_consts(self, a, a), + debug!("TypeGeneralizer::consts(a={:?})", a); + + if let ty::Const { val: ConstValue::Infer(InferConst::Canonical(_, _)), .. } = a { + bug!( + "unexpected inference variable encountered in NLL generalization: {:?}", + a + ); + } else { + relate::super_relate_consts(self, a, a) } } diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index bd19a002fe8b7..2e19c9c24e9b5 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -722,23 +722,23 @@ where ty::Closure(def_id, ref substs) => { // Skip lifetime parameters of the enclosing item(s) - for upvar_ty in substs.as_closure().upvar_tys(def_id, self.tcx) { + for upvar_ty in substs.upvar_tys(def_id, self.tcx) { upvar_ty.visit_with(self); } - substs.as_closure().sig_ty(def_id, self.tcx).visit_with(self); + substs.closure_sig_ty(def_id, self.tcx).visit_with(self); } ty::Generator(def_id, ref substs, _) => { // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. - for upvar_ty in substs.as_generator().upvar_tys(def_id, self.tcx) { + for upvar_ty in substs.upvar_tys(def_id, self.tcx) { upvar_ty.visit_with(self); } - substs.as_generator().return_ty(def_id, self.tcx).visit_with(self); - substs.as_generator().yield_ty(def_id, self.tcx).visit_with(self); + substs.return_ty(def_id, self.tcx).visit_with(self); + substs.yield_ty(def_id, self.tcx).visit_with(self); } _ => { ty.super_visit_with(self); @@ -886,7 +886,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { let generics = self.tcx.generics_of(def_id); let substs = - self.tcx.mk_substs(substs.iter().enumerate().map(|(index, &kind)| { + self.tcx.mk_substs(substs.substs.iter().enumerate().map(|(index, &kind)| { if index < generics.parent_count { // Accommodate missing regions in the parent kinds... self.fold_kind_mapping_missing_regions_to_empty(kind) @@ -896,13 +896,13 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { } })); - self.tcx.mk_closure(def_id, substs) + self.tcx.mk_closure(def_id, ty::ClosureSubsts { substs }) } ty::Generator(def_id, substs, movability) => { let generics = self.tcx.generics_of(def_id); let substs = - self.tcx.mk_substs(substs.iter().enumerate().map(|(index, &kind)| { + self.tcx.mk_substs(substs.substs.iter().enumerate().map(|(index, &kind)| { if index < generics.parent_count { // Accommodate missing regions in the parent kinds... self.fold_kind_mapping_missing_regions_to_empty(kind) @@ -912,7 +912,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { } })); - self.tcx.mk_generator(def_id, substs, movability) + self.tcx.mk_generator(def_id, ty::GeneratorSubsts { substs }, movability) } ty::Param(..) => { diff --git a/src/librustc/infer/region_constraints/leak_check.rs b/src/librustc/infer/region_constraints/leak_check.rs index 3d069425685c7..0c83bbc1e5394 100644 --- a/src/librustc/infer/region_constraints/leak_check.rs +++ b/src/librustc/infer/region_constraints/leak_check.rs @@ -14,11 +14,9 @@ impl<'tcx> RegionConstraintCollector<'tcx> { /// retain the older (arguably incorrect) behavior of the /// compiler. /// - /// NB. Although `_snapshot` isn't used, it's passed in to prove - /// that we are in a snapshot, which guarantees that we can just - /// search the "undo log" for edges. This is mostly an efficiency - /// thing -- we could search *all* region constraints, but that'd be - /// a bigger set and the data structures are not setup for that. If + /// NB. The use of snapshot here is mostly an efficiency thing -- + /// we could search *all* region constraints, but that'd be a + /// bigger set and the data structures are not setup for that. If /// we wind up keeping some form of this check long term, it would /// probably be better to remove the snapshot parameter and to /// refactor the constraint set. diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 8c6a7c9a376a7..21904edb309cb 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -7,7 +7,7 @@ use super::unify_key; use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_index::vec::IndexVec; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::Lrc; use rustc_data_structures::unify as ut; use crate::hir::def_id::DefId; @@ -116,7 +116,7 @@ pub struct RegionConstraintData<'tcx> { } /// Represents a constraint that influences the inference process. -#[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] pub enum Constraint<'tcx> { /// A region variable is a subregion of another. VarSubVar(RegionVid, RegionVid), diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs index 7c3a338366c9a..2db18674e2f53 100644 --- a/src/librustc/infer/resolve.rs +++ b/src/librustc/infer/resolve.rs @@ -1,7 +1,7 @@ use super::{InferCtxt, FixupError, FixupResult, Span}; use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::mir::interpret::ConstValue; -use crate::ty::{self, Ty, Const, TyCtxt, TypeFoldable, InferConst}; +use crate::ty::{self, Ty, Const, TyCtxt, TypeFoldable, InferConst, TypeFlags}; use crate::ty::fold::{TypeFolder, TypeVisitor}; /////////////////////////////////////////////////////////////////////////// @@ -29,7 +29,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.has_infer_types() && !t.has_infer_consts() { + if !t.has_infer_types() { t // micro-optimize -- if there is nothing in this type that this fold affects... } else { let t = self.infcx.shallow_resolve(t); @@ -38,7 +38,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> { } fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> { - if !ct.has_infer_consts() { + if !ct.has_type_flags(TypeFlags::HAS_CT_INFER) { ct // micro-optimize -- if there is nothing in this const that this fold affects... } else { let ct = self.infcx.shallow_resolve(ct); diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index f79a30c7ae8f3..ce1b54bb1c81d 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -1,4 +1,4 @@ -use syntax::symbol::Symbol; +use syntax::symbol::InternedString; use syntax_pos::Span; use crate::ty::{self, Ty, TyVid}; @@ -49,7 +49,7 @@ pub enum TypeVariableOriginKind { MiscVariable, NormalizeProjectionType, TypeInference, - TypeParameterDefinition(Symbol), + TypeParameterDefinition(InternedString), /// One of the upvars or closure kind parameters in a `ClosureSubsts` /// (before it has been determined). diff --git a/src/librustc/infer/unify_key.rs b/src/librustc/infer/unify_key.rs index b0b6d971c6087..846611db05427 100644 --- a/src/librustc/infer/unify_key.rs +++ b/src/librustc/infer/unify_key.rs @@ -3,7 +3,7 @@ use crate::mir::interpret::ConstValue; use rustc_data_structures::unify::{NoError, EqUnifyValue, UnifyKey, UnifyValue, UnificationTable}; use rustc_data_structures::unify::InPlace; use syntax_pos::{Span, DUMMY_SP}; -use syntax::symbol::Symbol; +use syntax::symbol::InternedString; use std::cmp; use std::marker::PhantomData; @@ -90,7 +90,7 @@ pub struct ConstVariableOrigin { pub enum ConstVariableOriginKind { MiscVariable, ConstInference, - ConstParameterDefinition(Symbol), + ConstParameterDefinition(InternedString), SubstitutionPlaceholder, } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 996f5b1241263..bd9899b644b5e 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -35,15 +35,15 @@ #![feature(const_transmute)] #![feature(core_intrinsics)] #![feature(drain_filter)] +#![feature(inner_deref)] #![cfg_attr(windows, feature(libc))] #![feature(never_type)] #![feature(exhaustive_patterns)] #![feature(overlapping_marker_traits)] #![feature(extern_types)] #![feature(nll)] -#![cfg_attr(bootstrap, feature(non_exhaustive))] +#![feature(non_exhaustive)] #![feature(optin_builtin_traits)] -#![feature(option_expect_none)] #![feature(range_is_empty)] #![feature(slice_patterns)] #![feature(specialization)] @@ -57,8 +57,9 @@ #![feature(test)] #![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(proc_macro_hygiene))] +#![feature(proc_macro_hygiene)] #![feature(log_syntax)] +#![feature(mem_take)] #![feature(associated_type_bounds)] #![feature(rustc_attrs)] @@ -101,12 +102,16 @@ pub mod lint; pub mod middle { pub mod expr_use_visitor; 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; + pub mod intrinsicck; pub mod lib_features; pub mod lang_items; + pub mod liveness; pub mod mem_categorization; pub mod privacy; pub mod reachable; diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 15598b60f5c0b..5906a6388a8bd 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -4,12 +4,11 @@ //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. -use crate::lint::{LintPass, LateLintPass, LintArray, FutureIncompatibleInfo}; +use crate::lint::{LintPass, LateLintPass, LintArray}; use crate::middle::stability; use crate::session::Session; use errors::{Applicability, DiagnosticBuilder, pluralise}; use syntax::ast; -use syntax::edition::Edition; use syntax::source_map::Span; use syntax::symbol::Symbol; @@ -22,8 +21,7 @@ declare_lint! { declare_lint! { pub CONST_ERR, Deny, - "constant evaluation detected erroneous expression", - report_in_external_macro + "constant evaluation detected erroneous expression" } declare_lint! { @@ -72,7 +70,7 @@ declare_lint! { pub UNREACHABLE_CODE, Warn, "detects unreachable code paths", - report_in_external_macro + report_in_external_macro: true } declare_lint! { @@ -81,12 +79,6 @@ declare_lint! { "detects unreachable patterns" } -declare_lint! { - pub OVERLAPPING_PATTERNS, - Warn, - "detects overlapping patterns" -} - declare_lint! { pub UNUSED_MACROS, Warn, @@ -132,11 +124,7 @@ declare_lint! { declare_lint! { pub PRIVATE_IN_PUBLIC, Warn, - "detect private items in public interfaces not caught by the old implementation", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #34537 ", - edition: None, - }; + "detect private items in public interfaces not caught by the old implementation" } declare_lint! { @@ -148,21 +136,13 @@ declare_lint! { declare_lint! { pub PUB_USE_OF_PRIVATE_EXTERN_CRATE, Deny, - "detect public re-exports of private extern crates", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #34537 ", - edition: None, - }; + "detect public re-exports of private extern crates" } declare_lint! { pub INVALID_TYPE_PARAM_DEFAULT, Deny, - "type parameter default erroneously allowed in invalid location", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #36887 ", - edition: None, - }; + "type parameter default erroneously allowed in invalid location" } declare_lint! { @@ -174,99 +154,63 @@ declare_lint! { declare_lint! { pub SAFE_EXTERN_STATICS, Deny, - "safe access to extern statics was erroneously allowed", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #36247 ", - edition: None, - }; + "safe access to extern statics was erroneously allowed" } declare_lint! { pub SAFE_PACKED_BORROWS, Warn, - "safe borrows of fields of packed structs were was erroneously allowed", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #46043 ", - edition: None, - }; + "safe borrows of fields of packed structs were was erroneously allowed" } declare_lint! { pub PATTERNS_IN_FNS_WITHOUT_BODY, Warn, - "patterns in functions without body were erroneously allowed", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #35203 ", - edition: None, - }; + "patterns in functions without body were erroneously allowed" } declare_lint! { pub LEGACY_DIRECTORY_OWNERSHIP, Deny, "non-inline, non-`#[path]` modules (e.g., `mod foo;`) were erroneously allowed in some files \ - not named `mod.rs`", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #37872 ", - edition: None, - }; + not named `mod.rs`" } declare_lint! { pub LEGACY_CONSTRUCTOR_VISIBILITY, Deny, - "detects use of struct constructors that would be invisible with new visibility rules", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #39207 ", - edition: None, - }; + "detects use of struct constructors that would be invisible with new visibility rules" } declare_lint! { pub MISSING_FRAGMENT_SPECIFIER, Deny, - "detects missing fragment specifiers in unused `macro_rules!` patterns", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #40107 ", - edition: None, - }; + "detects missing fragment specifiers in unused `macro_rules!` patterns" } declare_lint! { pub PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, Deny, - "detects parenthesized generic parameters in type and module names", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #42238 ", - edition: None, - }; + "detects parenthesized generic parameters in type and module names" } declare_lint! { pub LATE_BOUND_LIFETIME_ARGUMENTS, Warn, - "detects generic lifetime arguments in path segments with late bound lifetime parameters", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #42868 ", - edition: None, - }; + "detects generic lifetime arguments in path segments with late bound lifetime parameters" } declare_lint! { pub ORDER_DEPENDENT_TRAIT_OBJECTS, Deny, - "trait-object types were treated as different depending on marker-trait order", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #56484 ", - edition: None, - }; + "trait-object types were treated as different depending on marker-trait order" } declare_lint! { pub DEPRECATED, Warn, "detects use of deprecated items", - report_in_external_macro + report_in_external_macro: true } declare_lint! { @@ -302,11 +246,7 @@ declare_lint! { declare_lint! { pub TYVAR_BEHIND_RAW_POINTER, Warn, - "raw pointer to an inference variable", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #46906 ", - edition: Some(Edition::Edition2018), - }; + "raw pointer to an inference variable" } declare_lint! { @@ -325,33 +265,19 @@ declare_lint! { pub ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, Allow, "fully qualified paths that start with a module name \ - instead of `crate`, `self`, or an extern crate name", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #53130 ", - edition: Some(Edition::Edition2018), - }; + instead of `crate`, `self`, or an extern crate name" } declare_lint! { pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, Warn, - "floating-point literals cannot be used in patterns", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #41620 ", - edition: None, - }; + "floating-point literals cannot be used in patterns" } declare_lint! { pub UNSTABLE_NAME_COLLISIONS, Warn, - "detects name collision with an existing but unstable method", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #48919 ", - edition: None, - // Note: this item represents future incompatibility of all unstable functions in the - // standard library, and thus should never be removed or changed to an error. - }; + "detects name collision with an existing but unstable method" } declare_lint! { @@ -369,11 +295,7 @@ declare_lint! { declare_lint! { pub DUPLICATE_MACRO_EXPORTS, Deny, - "detects duplicate macro exports", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #35896 ", - edition: Some(Edition::Edition2018), - }; + "detects duplicate macro exports" } declare_lint! { @@ -397,21 +319,13 @@ declare_lint! { declare_lint! { pub WHERE_CLAUSES_OBJECT_SAFETY, Warn, - "checks the object safety of where clauses", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #51443 ", - edition: None, - }; + "checks the object safety of where clauses" } declare_lint! { pub PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, Warn, - "detects proc macro derives using inaccessible names from parent modules", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #50504 ", - edition: None, - }; + "detects proc macro derives using inaccessible names from parent modules" } declare_lint! { @@ -425,11 +339,7 @@ declare_lint! { pub MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, Deny, "macro-expanded `macro_export` macros from the current crate \ - cannot be referred to by absolute paths", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #52234 ", - edition: None, - }; + cannot be referred to by absolute paths" } declare_lint! { @@ -442,11 +352,7 @@ declare_lint! { pub INDIRECT_STRUCTURAL_MATCH, // defaulting to allow until rust-lang/rust#62614 is fixed. Allow, - "pattern with const indirectly referencing non-`#[structural_match]` type", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #62411 ", - edition: None, - }; + "pattern with const indirectly referencing non-`#[structural_match]` type" } /// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`. @@ -454,11 +360,7 @@ pub mod parser { declare_lint! { pub ILL_FORMED_ATTRIBUTE_INPUT, Warn, - "ill-formed attribute inputs that were previously accepted and used in practice", - @future_incompatible = super::FutureIncompatibleInfo { - reference: "issue #57571 ", - edition: None, - }; + "ill-formed attribute inputs that were previously accepted and used in practice" } declare_lint! { @@ -466,59 +368,37 @@ pub mod parser { Allow, "possible meta-variable misuse at macro definition" } - - declare_lint! { - pub INCOMPLETE_INCLUDE, - Deny, - "trailing content in included file" - } } declare_lint! { pub DEPRECATED_IN_FUTURE, Allow, "detects use of items that will be deprecated in a future version", - report_in_external_macro + report_in_external_macro: true } declare_lint! { pub AMBIGUOUS_ASSOCIATED_ITEMS, Deny, - "ambiguous associated items", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #57644 ", - edition: None, - }; + "ambiguous associated items" } declare_lint! { pub NESTED_IMPL_TRAIT, Warn, - "nested occurrence of `impl Trait` type", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #59014 ", - edition: None, - }; + "nested occurrence of `impl Trait` type" } declare_lint! { pub MUTABLE_BORROW_RESERVATION_CONFLICT, Warn, - "reservation of a two-phased borrow conflicts with other shared borrows", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #59159 ", - edition: None, - }; + "reservation of a two-phased borrow conflicts with other shared borrows" } declare_lint! { pub SOFT_UNSTABLE, Deny, - "a feature gate that doesn't break dependent crates", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #64266 ", - edition: None, - }; + "a feature gate that doesn't break dependent crates" } declare_lint_pass! { @@ -536,7 +416,6 @@ declare_lint_pass! { DEAD_CODE, UNREACHABLE_CODE, UNREACHABLE_PATTERNS, - OVERLAPPING_PATTERNS, UNUSED_MACROS, WARNINGS, UNUSED_FEATURES, diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 1cb53d754dcd3..fa73a3c6c4628 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -22,11 +22,11 @@ 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::{Level, Lint, LintId, LintPass, LintBuffer, FutureIncompatibleInfo}; +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 crate::session::Session; +use crate::session::{config, early_error, Session}; use crate::ty::{self, print::Printer, subst::GenericArg, TyCtxt, Ty}; use crate::ty::layout::{LayoutError, LayoutOf, TyLayout}; use crate::util::nodemap::FxHashMap; @@ -35,9 +35,10 @@ use crate::util::common::time; use errors::DiagnosticBuilder; use std::slice; use std::default::Default as StdDefault; -use rustc_data_structures::sync::{self, ParallelIterator, join, par_iter}; +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::util::lev_distance::find_best_match_for_name; use syntax::visit as ast_visit; use syntax_pos::{MultiSpan, Span, symbol::Symbol}; @@ -49,25 +50,24 @@ use syntax_pos::{MultiSpan, Span, symbol::Symbol}; pub struct LintStore { /// Registered lints. The bool is true if the lint was /// added by a plugin. - lints: Vec<&'static Lint>, + lints: Vec<(&'static Lint, bool)>, - /// Constructor functions for each variety of lint pass. - /// - /// These should only be called once, but since we want to avoid locks or - /// interior mutability, we don't enforce this (and lints should, in theory, - /// be compatible with being constructed more than once, though not - /// necessarily in a sane manner. This is safe though.) - pre_expansion_passes: Vec EarlyLintPassObject + sync::Send + sync::Sync>>, - early_passes: Vec EarlyLintPassObject + sync::Send + sync::Sync>>, - late_passes: Vec LateLintPassObject + sync::Send + sync::Sync>>, - /// This is unique in that we construct them per-module, so not once. - late_module_passes: Vec LateLintPassObject + sync::Send + sync::Sync>>, + /// Trait objects for each lint pass. + /// This is only `None` while performing a lint pass. + pre_expansion_passes: Option>, + early_passes: Option>, + late_passes: Lock>>, + late_module_passes: Vec, /// Lints indexed by name. by_name: FxHashMap, /// Map of registered lint groups to what lints they expand to. lint_groups: FxHashMap<&'static str, LintGroup>, + + /// Extra info for future incompatibility lints, describing the + /// issue or RFC that caused the incompatibility. + future_incompatible: FxHashMap, } /// Lints that are buffered up early on in the `Session` before the @@ -81,6 +81,18 @@ pub struct BufferedEarlyLint { pub diagnostic: BuiltinLintDiagnostics, } +/// Extra information for a future incompatibility lint. See the call +/// to `register_future_incompatible` in `librustc_lint/lib.rs` for +/// guidelines. +pub struct FutureIncompatibleInfo { + pub id: LintId, + /// e.g., a URL for an issue/PR/RFC or error code + pub reference: &'static str, + /// If this is an edition fixing lint, the edition in which + /// this lint becomes obsolete + pub edition: Option, +} + /// The target of the `by_name` map, which accounts for renaming/deprecation. enum TargetLint { /// A direct lint target @@ -130,16 +142,17 @@ impl LintStore { pub fn new() -> LintStore { LintStore { lints: vec![], - pre_expansion_passes: vec![], - early_passes: vec![], - late_passes: vec![], + pre_expansion_passes: Some(vec![]), + early_passes: Some(vec![]), + late_passes: Lock::new(Some(vec![])), late_module_passes: vec![], by_name: Default::default(), + future_incompatible: Default::default(), lint_groups: Default::default(), } } - pub fn get_lints<'t>(&'t self) -> &'t [&'static Lint] { + pub fn get_lints<'t>(&'t self) -> &'t [(&'static Lint, bool)] { &self.lints } @@ -155,64 +168,99 @@ impl LintStore { .collect() } - pub fn register_early_pass( - &mut self, - pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync - ) { - self.early_passes.push(Box::new(pass)); + pub fn register_early_pass(&mut self, + sess: Option<&Session>, + from_plugin: bool, + register_only: bool, + pass: EarlyLintPassObject) { + self.push_pass(sess, from_plugin, &pass); + if !register_only { + self.early_passes.as_mut().unwrap().push(pass); + } } pub fn register_pre_expansion_pass( &mut self, - pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync, - ) { - self.pre_expansion_passes.push(Box::new(pass)); - } - - pub fn register_late_pass( - &mut self, - pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync, + sess: Option<&Session>, + from_plugin: bool, + register_only: bool, + pass: EarlyLintPassObject, ) { - self.late_passes.push(Box::new(pass)); + self.push_pass(sess, from_plugin, &pass); + if !register_only { + self.pre_expansion_passes.as_mut().unwrap().push(pass); + } } - pub fn register_late_mod_pass( - &mut self, - pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync, - ) { - self.late_module_passes.push(Box::new(pass)); + pub fn register_late_pass(&mut self, + sess: Option<&Session>, + from_plugin: bool, + register_only: bool, + per_module: bool, + pass: LateLintPassObject) { + self.push_pass(sess, from_plugin, &pass); + if !register_only { + if per_module { + self.late_module_passes.push(pass); + } else { + self.late_passes.lock().as_mut().unwrap().push(pass); + } + } } // Helper method for register_early/late_pass - pub fn register_lints(&mut self, lints: &[&'static Lint]) { - for lint in lints { - self.lints.push(lint); + fn push_pass(&mut self, + sess: Option<&Session>, + from_plugin: bool, + pass: &Box